typedef of template classes are always default constructed?

Discussion in 'C++' started by aaragon, Nov 7, 2006.

  1. aaragon

    aaragon Guest

    Hello all. I have a simple question that seems trivial but I can't
    make it to work. I have a class that takes as a template argument,
    another class. The idea is as follows:

    #include <iostream>

    using namespace std;

    template <class ClassB>
    class ClassA
    {
    int a;
    ClassB cb;

    public:

    void print(){
    cout<<"print within class A"<<endl;
    }
    };

    class ClassB
    {
    int s_;

    public:

    ClassB(int s) : s_(s) {}
    };

    int main()
    {
    typedef ClassA<ClassB> CA;
    CA ca;
    ca.print();

    return 0;
    }

    The thing is that when I try to compile this code, I receive the
    message:
    main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    main2.cxx:7: error: no matching function for call to
    'ClassB::ClassB()'
    main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    main2.cxx: In function 'int main()':
    main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    first required here

    Of course because I don't provide a default constructor. If I change
    within main() to something like

    typedef ClassA<ClassB(6)> CA;

    I receive the error:

    main2.cxx: In function 'int main()':
    main2.cxx:29: error: a call to a constructor cannot appear in a
    constant-expression
    main2.cxx:29: error: template argument 1 is invalid
    main2.cxx:29: error: invalid type in declaration before ';' token
    main2.cxx:31: error: request for member 'print' in 'ca', which
    is of non-class type 'main::CA'

    Furthermore, if I change the code to
    ClassB cb(6);
    typedef ClassA<cb> CA;

    I receive the same error. What am I doing wrong? I don't want the
    class be to be default constructed within the type definition. Thanks
    for your help.

    aa
     
    aaragon, Nov 7, 2006
    #1
    1. Advertising

  2. aaragon

    mlimber Guest

    aaragon wrote:
    > Hello all. I have a simple question that seems trivial but I can't
    > make it to work. I have a class that takes as a template argument,
    > another class. The idea is as follows:
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > template <class ClassB>
    > class ClassA
    > {
    > int a;
    > ClassB cb;
    >
    > public:
    >
    > void print(){
    > cout<<"print within class A"<<endl;
    > }
    > };
    >
    > class ClassB
    > {
    > int s_;
    >
    > public:
    >
    > ClassB(int s) : s_(s) {}
    > };
    >
    > int main()
    > {
    > typedef ClassA<ClassB> CA;
    > CA ca;
    > ca.print();
    >
    > return 0;
    > }
    >
    > The thing is that when I try to compile this code, I receive the
    > message:
    > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > main2.cxx:7: error: no matching function for call to
    > 'ClassB::ClassB()'
    > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > main2.cxx: In function 'int main()':
    > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > first required here
    >
    > Of course because I don't provide a default constructor. If I change
    > within main() to something like
    >
    > typedef ClassA<ClassB(6)> CA;
    >
    > I receive the error:
    >
    > main2.cxx: In function 'int main()':
    > main2.cxx:29: error: a call to a constructor cannot appear in a
    > constant-expression
    > main2.cxx:29: error: template argument 1 is invalid
    > main2.cxx:29: error: invalid type in declaration before ';' token
    > main2.cxx:31: error: request for member 'print' in 'ca', which
    > is of non-class type 'main::CA'
    >
    > Furthermore, if I change the code to
    > ClassB cb(6);
    > typedef ClassA<cb> CA;
    >
    > I receive the same error. What am I doing wrong? I don't want the
    > class be to be default constructed within the type definition. Thanks
    > for your help.


    Templates can take types or (integral) constant expressions as
    parameters, and these parameters must be available at *compile time*.
    Creating an object instance like cb or ClassB(6) are both run-time
    operations. You must either provide a default constructor (or a default
    parameter on your existing constructor), or pass to ClassA<>'s
    constructor the necessary parameters to initalize class B.

    Cheers! --M
     
    mlimber, Nov 7, 2006
    #2
    1. Advertising

  3. aaragon

    Salt_Peter Guest

    aaragon wrote:
    > Hello all. I have a simple question that seems trivial but I can't
    > make it to work. I have a class that takes as a template argument,
    > another class. The idea is as follows:
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > template <class ClassB>
    > class ClassA
    > {
    > int a;
    > ClassB cb;
    >
    > public:
    >
    > void print(){
    > cout<<"print within class A"<<endl;
    > }
    > };
    >
    > class ClassB
    > {
    > int s_;
    >
    > public:
    >
    > ClassB(int s) : s_(s) {}
    > };
    >
    > int main()
    > {
    > typedef ClassA<ClassB> CA;
    > CA ca;
    > ca.print();
    >
    > return 0;
    > }
    >
    > The thing is that when I try to compile this code, I receive the
    > message:
    > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > main2.cxx:7: error: no matching function for call to
    > 'ClassB::ClassB()'
    > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > main2.cxx: In function 'int main()':
    > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > first required here
    >
    > Of course because I don't provide a default constructor. If I change
    > within main() to something like
    >
    > typedef ClassA<ClassB(6)> CA;
    >
    > I receive the error:
    >
    > main2.cxx: In function 'int main()':
    > main2.cxx:29: error: a call to a constructor cannot appear in a
    > constant-expression
    > main2.cxx:29: error: template argument 1 is invalid
    > main2.cxx:29: error: invalid type in declaration before ';' token
    > main2.cxx:31: error: request for member 'print' in 'ca', which
    > is of non-class type 'main::CA'
    >
    > Furthermore, if I change the code to
    > ClassB cb(6);
    > typedef ClassA<cb> CA;
    >
    > I receive the same error. What am I doing wrong? I don't want the
    > class be to be default constructed within the type definition. Thanks
    > for your help.
    >
    > aa


    Whats preventing you from providing a default ctor in ClassB?

    class ClassB
    {
    int s_;
    public:
    ClassB() : s_(0) { }
    };

    // or alternatively, one in ClassA:

    template <class T>
    class ClassA
    {
    int a;
    T t;
    public:
    ClassA() : a(0), t(0) { }
    void print() const { ... }
    };

    By the way, its never, never, a good idea _not_ to initialize ALL of
    your members.
    Even when these will be changed afterwards.
     
    Salt_Peter, Nov 7, 2006
    #3
  4. aaragon

    Guest

    could anyone explain why the above program works if pointer is used ?
     
    , Nov 8, 2006
    #4
  5. aaragon

    mlimber Guest

    wrote:
    > could anyone explain why the above program works if pointer is used ?


    If a pointer is used where?

    Cheers! --M
     
    mlimber, Nov 8, 2006
    #5
  6. aaragon

    aaragon Guest

    Salt_Peter wrote:
    > aaragon wrote:
    > > Hello all. I have a simple question that seems trivial but I can't
    > > make it to work. I have a class that takes as a template argument,
    > > another class. The idea is as follows:
    > >
    > > #include <iostream>
    > >
    > > using namespace std;
    > >
    > > template <class ClassB>
    > > class ClassA
    > > {
    > > int a;
    > > ClassB cb;
    > >
    > > public:
    > >
    > > void print(){
    > > cout<<"print within class A"<<endl;
    > > }
    > > };
    > >
    > > class ClassB
    > > {
    > > int s_;
    > >
    > > public:
    > >
    > > ClassB(int s) : s_(s) {}
    > > };
    > >
    > > int main()
    > > {
    > > typedef ClassA<ClassB> CA;
    > > CA ca;
    > > ca.print();
    > >
    > > return 0;
    > > }
    > >
    > > The thing is that when I try to compile this code, I receive the
    > > message:
    > > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > > main2.cxx:7: error: no matching function for call to
    > > 'ClassB::ClassB()'
    > > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > > main2.cxx: In function 'int main()':
    > > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > > first required here
    > >
    > > Of course because I don't provide a default constructor. If I change
    > > within main() to something like
    > >
    > > typedef ClassA<ClassB(6)> CA;
    > >
    > > I receive the error:
    > >
    > > main2.cxx: In function 'int main()':
    > > main2.cxx:29: error: a call to a constructor cannot appear in a
    > > constant-expression
    > > main2.cxx:29: error: template argument 1 is invalid
    > > main2.cxx:29: error: invalid type in declaration before ';' token
    > > main2.cxx:31: error: request for member 'print' in 'ca', which
    > > is of non-class type 'main::CA'
    > >
    > > Furthermore, if I change the code to
    > > ClassB cb(6);
    > > typedef ClassA<cb> CA;
    > >
    > > I receive the same error. What am I doing wrong? I don't want the
    > > class be to be default constructed within the type definition. Thanks
    > > for your help.
    > >
    > > aa

    >
    > Whats preventing you from providing a default ctor in ClassB?
    >


    Well, I would like the user within main() to chose the required
    paramter. For this class, a default parameter for this variable does
    not make sense. I could initialize the variable to a default and
    change it later on, but this is not very elegant. I thought that maybe
    there was a way to do it at compile time.

    > class ClassB
    > {
    > int s_;
    > public:
    > ClassB() : s_(0) { }
    > };
    >
    > // or alternatively, one in ClassA:
    >
    > template <class T>
    > class ClassA
    > {
    > int a;
    > T t;
    > public:
    > ClassA() : a(0), t(0) { }
    > void print() const { ... }
    > };
    >
    > By the way, its never, never, a good idea _not_ to initialize ALL of
    > your members.
    > Even when these will be changed afterwards.
     
    aaragon, Nov 8, 2006
    #6
  7. aaragon

    mlimber Guest

    aaragon wrote:
    > Salt_Peter wrote:
    > > aaragon wrote:
    > > > Hello all. I have a simple question that seems trivial but I can't
    > > > make it to work. I have a class that takes as a template argument,
    > > > another class. The idea is as follows:
    > > >
    > > > #include <iostream>
    > > >
    > > > using namespace std;
    > > >
    > > > template <class ClassB>
    > > > class ClassA
    > > > {
    > > > int a;
    > > > ClassB cb;
    > > >
    > > > public:
    > > >
    > > > void print(){
    > > > cout<<"print within class A"<<endl;
    > > > }
    > > > };
    > > >
    > > > class ClassB
    > > > {
    > > > int s_;
    > > >
    > > > public:
    > > >
    > > > ClassB(int s) : s_(s) {}
    > > > };
    > > >
    > > > int main()
    > > > {
    > > > typedef ClassA<ClassB> CA;
    > > > CA ca;
    > > > ca.print();
    > > >
    > > > return 0;
    > > > }
    > > >
    > > > The thing is that when I try to compile this code, I receive the
    > > > message:
    > > > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > > > main2.cxx:7: error: no matching function for call to
    > > > 'ClassB::ClassB()'
    > > > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > > > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > > > main2.cxx: In function 'int main()':
    > > > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > > > first required here
    > > >
    > > > Of course because I don't provide a default constructor. If I change
    > > > within main() to something like
    > > >
    > > > typedef ClassA<ClassB(6)> CA;
    > > >
    > > > I receive the error:
    > > >
    > > > main2.cxx: In function 'int main()':
    > > > main2.cxx:29: error: a call to a constructor cannot appear in a
    > > > constant-expression
    > > > main2.cxx:29: error: template argument 1 is invalid
    > > > main2.cxx:29: error: invalid type in declaration before ';' token
    > > > main2.cxx:31: error: request for member 'print' in 'ca', which
    > > > is of non-class type 'main::CA'
    > > >
    > > > Furthermore, if I change the code to
    > > > ClassB cb(6);
    > > > typedef ClassA<cb> CA;
    > > >
    > > > I receive the same error. What am I doing wrong? I don't want the
    > > > class be to be default constructed within the type definition. Thanks
    > > > for your help.
    > > >

    > >
    > > Whats preventing you from providing a default ctor in ClassB?
    > >

    >
    > Well, I would like the user within main() to chose the required
    > paramter. For this class, a default parameter for this variable does
    > not make sense. I could initialize the variable to a default and
    > change it later on, but this is not very elegant. I thought that maybe
    > there was a way to do it at compile time.


    So have ClassA accept a parameter for ClassB's constructor like I
    suggested elsethread. This puts a requirement on all types used as a
    template parameter to ClassA, but that's the way templates work.

    Cheers! --M
     
    mlimber, Nov 8, 2006
    #7
  8. aaragon

    aaragon Guest

    mlimber wrote:
    > aaragon wrote:
    > > Salt_Peter wrote:
    > > > aaragon wrote:
    > > > > Hello all. I have a simple question that seems trivial but I can't
    > > > > make it to work. I have a class that takes as a template argument,
    > > > > another class. The idea is as follows:
    > > > >
    > > > > #include <iostream>
    > > > >
    > > > > using namespace std;
    > > > >
    > > > > template <class ClassB>
    > > > > class ClassA
    > > > > {
    > > > > int a;
    > > > > ClassB cb;
    > > > >
    > > > > public:
    > > > >
    > > > > void print(){
    > > > > cout<<"print within class A"<<endl;
    > > > > }
    > > > > };
    > > > >
    > > > > class ClassB
    > > > > {
    > > > > int s_;
    > > > >
    > > > > public:
    > > > >
    > > > > ClassB(int s) : s_(s) {}
    > > > > };
    > > > >
    > > > > int main()
    > > > > {
    > > > > typedef ClassA<ClassB> CA;
    > > > > CA ca;
    > > > > ca.print();
    > > > >
    > > > > return 0;
    > > > > }
    > > > >
    > > > > The thing is that when I try to compile this code, I receive the
    > > > > message:
    > > > > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > > > > main2.cxx:7: error: no matching function for call to
    > > > > 'ClassB::ClassB()'
    > > > > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > > > > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > > > > main2.cxx: In function 'int main()':
    > > > > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > > > > first required here
    > > > >
    > > > > Of course because I don't provide a default constructor. If I change
    > > > > within main() to something like
    > > > >
    > > > > typedef ClassA<ClassB(6)> CA;
    > > > >
    > > > > I receive the error:
    > > > >
    > > > > main2.cxx: In function 'int main()':
    > > > > main2.cxx:29: error: a call to a constructor cannot appear in a
    > > > > constant-expression
    > > > > main2.cxx:29: error: template argument 1 is invalid
    > > > > main2.cxx:29: error: invalid type in declaration before ';' token
    > > > > main2.cxx:31: error: request for member 'print' in 'ca', which
    > > > > is of non-class type 'main::CA'
    > > > >
    > > > > Furthermore, if I change the code to
    > > > > ClassB cb(6);
    > > > > typedef ClassA<cb> CA;
    > > > >
    > > > > I receive the same error. What am I doing wrong? I don't want the
    > > > > class be to be default constructed within the type definition. Thanks
    > > > > for your help.
    > > > >
    > > >
    > > > Whats preventing you from providing a default ctor in ClassB?
    > > >

    > >
    > > Well, I would like the user within main() to chose the required
    > > paramter. For this class, a default parameter for this variable does
    > > not make sense. I could initialize the variable to a default and
    > > change it later on, but this is not very elegant. I thought that maybe
    > > there was a way to do it at compile time.

    >
    > So have ClassA accept a parameter for ClassB's constructor like I
    > suggested elsethread. This puts a requirement on all types used as a
    > template parameter to ClassA, but that's the way templates work.
    >
    > Cheers! --M


    I got it!!! There is another way. After reading chapter 2 of Modern
    C++ Design (Alexandrescu) I found out that you can do this at compile
    time. The solution is as follows:

    #include <iostream>

    using namespace std;

    template<int v>
    struct Int2Type
    {
    enum {value = v };
    };

    template <class ClassB>
    class ClassA
    {
    int a;
    ClassB cb;

    public:

    void print(){
    cout<<"print within class A"<<endl;
    cout<<"print value s of class B: "<<cb.s()<<endl;
    }
    };

    template <class T>
    class ClassB
    {
    int s_;

    public:

    ClassB() : s_(T::value) {}

    int s() {return s_;}

    };

    int main()
    {
    typedef ClassA<ClassB<Int2Type<4> > > CA;
    CA ca;
    ca.print();

    return 0;
    }

    This works perfectly!!! Thank you guys.

    aa
     
    aaragon, Nov 8, 2006
    #8
  9. aaragon

    mlimber Guest

    aaragon wrote:

    > I got it!!! There is another way. After reading chapter 2 of Modern
    > C++ Design (Alexandrescu) I found out that you can do this at compile
    > time. The solution is as follows:
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > template<int v>
    > struct Int2Type
    > {
    > enum {value = v };
    > };
    >
    > template <class ClassB>
    > class ClassA
    > {
    > int a;
    > ClassB cb;
    >
    > public:
    >
    > void print(){
    > cout<<"print within class A"<<endl;
    > cout<<"print value s of class B: "<<cb.s()<<endl;
    > }
    > };
    >
    > template <class T>
    > class ClassB
    > {
    > int s_;
    >
    > public:
    >
    > ClassB() : s_(T::value) {}
    >
    > int s() {return s_;}
    >
    > };
    >
    > int main()
    > {
    > typedef ClassA<ClassB<Int2Type<4> > > CA;
    > CA ca;
    > ca.print();
    >
    > return 0;
    > }
    >
    > This works perfectly!!! Thank you guys.


    Ok, now I see more clearly what you were trying to do. In the end, you
    still provided a default constructor for ClassB, but the Int2Type in
    your solution is unnecessary. Just make it:

    template<int i>
    class B
    {
    int s_;
    public:
    B() : s_(i) {}
    };

    In general, I'd prefer to use more conventional methods when they will
    suffice:

    template<class T>
    class A
    {
    T t_;
    public:
    A( const T& t ) : t_(t) {}
    };

    class B
    {
    int s_;
    public:
    B( int s ) : s_(s) {}
    };

    void Foo()
    {
    B b( 6 );
    A a( b );
    // ...
    }

    Cheers! --M
     
    mlimber, Nov 8, 2006
    #9
  10. aaragon

    aaragon Guest

    mlimber wrote:
    > aaragon wrote:
    >
    > > I got it!!! There is another way. After reading chapter 2 of Modern
    > > C++ Design (Alexandrescu) I found out that you can do this at compile
    > > time. The solution is as follows:
    > >
    > > #include <iostream>
    > >
    > > using namespace std;
    > >
    > > template<int v>
    > > struct Int2Type
    > > {
    > > enum {value = v };
    > > };
    > >
    > > template <class ClassB>
    > > class ClassA
    > > {
    > > int a;
    > > ClassB cb;
    > >
    > > public:
    > >
    > > void print(){
    > > cout<<"print within class A"<<endl;
    > > cout<<"print value s of class B: "<<cb.s()<<endl;
    > > }
    > > };
    > >
    > > template <class T>
    > > class ClassB
    > > {
    > > int s_;
    > >
    > > public:
    > >
    > > ClassB() : s_(T::value) {}
    > >
    > > int s() {return s_;}
    > >
    > > };
    > >
    > > int main()
    > > {
    > > typedef ClassA<ClassB<Int2Type<4> > > CA;
    > > CA ca;
    > > ca.print();
    > >
    > > return 0;
    > > }
    > >
    > > This works perfectly!!! Thank you guys.

    >
    > Ok, now I see more clearly what you were trying to do. In the end, you
    > still provided a default constructor for ClassB, but the Int2Type in
    > your solution is unnecessary. Just make it:
    >
    > template<int i>
    > class B
    > {
    > int s_;
    > public:
    > B() : s_(i) {}
    > };
    >
    > In general, I'd prefer to use more conventional methods when they will
    > suffice:
    >
    > template<class T>
    > class A
    > {
    > T t_;
    > public:
    > A( const T& t ) : t_(t) {}
    > };
    >
    > class B
    > {
    > int s_;
    > public:
    > B( int s ) : s_(s) {}
    > };
    >
    > void Foo()
    > {
    > B b( 6 );
    > A a( b );
    > // ...
    > }
    >
    > Cheers! --M


    Thanks mlimber!
     
    aaragon, Nov 8, 2006
    #10
  11. aaragon

    Salt_Peter Guest

    aaragon wrote:
    > mlimber wrote:
    > > aaragon wrote:
    > > > Salt_Peter wrote:
    > > > > aaragon wrote:
    > > > > > Hello all. I have a simple question that seems trivial but I can't
    > > > > > make it to work. I have a class that takes as a template argument,
    > > > > > another class. The idea is as follows:
    > > > > >
    > > > > > #include <iostream>
    > > > > >
    > > > > > using namespace std;
    > > > > >
    > > > > > template <class ClassB>
    > > > > > class ClassA
    > > > > > {
    > > > > > int a;
    > > > > > ClassB cb;
    > > > > >
    > > > > > public:
    > > > > >
    > > > > > void print(){
    > > > > > cout<<"print within class A"<<endl;
    > > > > > }
    > > > > > };
    > > > > >
    > > > > > class ClassB
    > > > > > {
    > > > > > int s_;
    > > > > >
    > > > > > public:
    > > > > >
    > > > > > ClassB(int s) : s_(s) {}
    > > > > > };
    > > > > >
    > > > > > int main()
    > > > > > {
    > > > > > typedef ClassA<ClassB> CA;
    > > > > > CA ca;
    > > > > > ca.print();
    > > > > >
    > > > > > return 0;
    > > > > > }
    > > > > >
    > > > > > The thing is that when I try to compile this code, I receive the
    > > > > > message:
    > > > > > main2.cxx: In constructor 'ClassA<ClassB>::ClassA()':
    > > > > > main2.cxx:7: error: no matching function for call to
    > > > > > 'ClassB::ClassB()'
    > > > > > main2.cxx:24: note: candidates are: ClassB::ClassB(int)
    > > > > > main2.cxx:19: note: ClassB::ClassB(const ClassB&)
    > > > > > main2.cxx: In function 'int main()':
    > > > > > main2.cxx:30: note: synthesized method 'ClassA<ClassB>::ClassA()'
    > > > > > first required here
    > > > > >
    > > > > > Of course because I don't provide a default constructor. If I change
    > > > > > within main() to something like
    > > > > >
    > > > > > typedef ClassA<ClassB(6)> CA;
    > > > > >
    > > > > > I receive the error:
    > > > > >
    > > > > > main2.cxx: In function 'int main()':
    > > > > > main2.cxx:29: error: a call to a constructor cannot appear in a
    > > > > > constant-expression
    > > > > > main2.cxx:29: error: template argument 1 is invalid
    > > > > > main2.cxx:29: error: invalid type in declaration before ';' token
    > > > > > main2.cxx:31: error: request for member 'print' in 'ca', which
    > > > > > is of non-class type 'main::CA'
    > > > > >
    > > > > > Furthermore, if I change the code to
    > > > > > ClassB cb(6);
    > > > > > typedef ClassA<cb> CA;
    > > > > >
    > > > > > I receive the same error. What am I doing wrong? I don't want the
    > > > > > class be to be default constructed within the type definition. Thanks
    > > > > > for your help.
    > > > > >
    > > > >
    > > > > Whats preventing you from providing a default ctor in ClassB?
    > > > >
    > > >
    > > > Well, I would like the user within main() to chose the required
    > > > paramter. For this class, a default parameter for this variable does
    > > > not make sense. I could initialize the variable to a default and
    > > > change it later on, but this is not very elegant. I thought that maybe
    > > > there was a way to do it at compile time.

    > >
    > > So have ClassA accept a parameter for ClassB's constructor like I
    > > suggested elsethread. This puts a requirement on all types used as a
    > > template parameter to ClassA, but that's the way templates work.
    > >
    > > Cheers! --M

    >
    > I got it!!! There is another way. After reading chapter 2 of Modern
    > C++ Design (Alexandrescu) I found out that you can do this at compile
    > time. The solution is as follows:
    >
    > #include <iostream>
    >
    > using namespace std;
    >
    > template<int v>
    > struct Int2Type
    > {
    > enum {value = v };
    > };
    >
    > template <class ClassB>
    > class ClassA
    > {
    > int a;
    > ClassB cb;
    >
    > public:
    >
    > void print(){
    > cout<<"print within class A"<<endl;
    > cout<<"print value s of class B: "<<cb.s()<<endl;
    > }
    > };
    >
    > template <class T>
    > class ClassB
    > {
    > int s_;
    >
    > public:
    >
    > ClassB() : s_(T::value) {}
    >
    > int s() {return s_;}
    >
    > };
    >
    > int main()
    > {
    > typedef ClassA<ClassB<Int2Type<4> > > CA;
    > CA ca;
    > ca.print();
    >
    > return 0;
    > }
    >
    > This works perfectly!!! Thank you guys.
    >
    > aa


    I'ld kindly suggest respecting the constant-ness of your member
    functions.
    Any mem func that does not mutate the members should be const.
    How about a constant integer for a template param instead:

    template < class ClassB >
    class ClassA
    {
    int a;
    ClassB cb;
    public:
    void print() const {
    std::cout<<"print within class A"<<std::endl;
    std::cout<<"print value s of class B: "<<cb.getN()<<std::endl;
    }
    };

    template < const int N >
    class ClassB
    {
    int n;
    public:
    ClassB() : n(N) {}
    int getN() const {return n;}
    };

    int main()
    {
    typedef ClassA< ClassB< 4 > > CA;
    CA ca;
    ca.print();
    return 0;
    }
     
    Salt_Peter, Nov 8, 2006
    #11
  12. aaragon

    aaragon Guest

    mlimber wrote:
    > aaragon wrote:
    >
    > > I got it!!! There is another way. After reading chapter 2 of Modern
    > > C++ Design (Alexandrescu) I found out that you can do this at compile
    > > time. The solution is as follows:
    > >
    > > #include <iostream>
    > >
    > > using namespace std;
    > >
    > > template<int v>
    > > struct Int2Type
    > > {
    > > enum {value = v };
    > > };
    > >
    > > template <class ClassB>
    > > class ClassA
    > > {
    > > int a;
    > > ClassB cb;
    > >
    > > public:
    > >
    > > void print(){
    > > cout<<"print within class A"<<endl;
    > > cout<<"print value s of class B: "<<cb.s()<<endl;
    > > }
    > > };
    > >
    > > template <class T>
    > > class ClassB
    > > {
    > > int s_;
    > >
    > > public:
    > >
    > > ClassB() : s_(T::value) {}
    > >
    > > int s() {return s_;}
    > >
    > > };
    > >
    > > int main()
    > > {
    > > typedef ClassA<ClassB<Int2Type<4> > > CA;
    > > CA ca;
    > > ca.print();
    > >
    > > return 0;
    > > }
    > >
    > > This works perfectly!!! Thank you guys.

    >
    > Ok, now I see more clearly what you were trying to do. In the end, you
    > still provided a default constructor for ClassB, but the Int2Type in
    > your solution is unnecessary. Just make it:
    >
    > template<int i>
    > class B
    > {
    > int s_;
    > public:
    > B() : s_(i) {}
    > };
    >
    > In general, I'd prefer to use more conventional methods when they will
    > suffice:
    >
    > template<class T>
    > class A
    > {
    > T t_;
    > public:
    > A( const T& t ) : t_(t) {}
    > };
    >
    > class B
    > {
    > int s_;
    > public:
    > B( int s ) : s_(s) {}
    > };
    >
    > void Foo()
    > {
    > B b( 6 );
    > A a( b );
    > // ...
    > }
    >
    > Cheers! --M


    Thanks mlimber!
     
    aaragon, Nov 8, 2006
    #12
  13. aaragon

    aaragon Guest

    mlimber wrote:
    > aaragon wrote:
    >
    > > I got it!!! There is another way. After reading chapter 2 of Modern
    > > C++ Design (Alexandrescu) I found out that you can do this at compile
    > > time. The solution is as follows:
    > >
    > > #include <iostream>
    > >
    > > using namespace std;
    > >
    > > template<int v>
    > > struct Int2Type
    > > {
    > > enum {value = v };
    > > };
    > >
    > > template <class ClassB>
    > > class ClassA
    > > {
    > > int a;
    > > ClassB cb;
    > >
    > > public:
    > >
    > > void print(){
    > > cout<<"print within class A"<<endl;
    > > cout<<"print value s of class B: "<<cb.s()<<endl;
    > > }
    > > };
    > >
    > > template <class T>
    > > class ClassB
    > > {
    > > int s_;
    > >
    > > public:
    > >
    > > ClassB() : s_(T::value) {}
    > >
    > > int s() {return s_;}
    > >
    > > };
    > >
    > > int main()
    > > {
    > > typedef ClassA<ClassB<Int2Type<4> > > CA;
    > > CA ca;
    > > ca.print();
    > >
    > > return 0;
    > > }
    > >
    > > This works perfectly!!! Thank you guys.

    >
    > Ok, now I see more clearly what you were trying to do. In the end, you
    > still provided a default constructor for ClassB, but the Int2Type in
    > your solution is unnecessary. Just make it:
    >
    > template<int i>
    > class B
    > {
    > int s_;
    > public:
    > B() : s_(i) {}
    > };
    >
    > In general, I'd prefer to use more conventional methods when they will
    > suffice:
    >
    > template<class T>
    > class A
    > {
    > T t_;
    > public:
    > A( const T& t ) : t_(t) {}
    > };
    >
    > class B
    > {
    > int s_;
    > public:
    > B( int s ) : s_(s) {}
    > };
    >
    > void Foo()
    > {
    > B b( 6 );
    > A a( b );
    > // ...
    > }
    >
    > Cheers! --M


    Thanks mlimber!
     
    aaragon, Nov 8, 2006
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Paul
    Replies:
    8
    Views:
    440
    Rob Williscroft
    Dec 10, 2004
  2. Kristoffer Vinther

    Default constructed random access iteratators

    Kristoffer Vinther, May 17, 2005, in forum: C++
    Replies:
    1
    Views:
    342
    Ron Natalie
    May 18, 2005
  3. Robin Becker
    Replies:
    0
    Views:
    283
    Robin Becker
    Feb 15, 2005
  4. puzzlecracker
    Replies:
    1
    Views:
    282
    John Harrison
    Sep 16, 2005
  5. Clemens Hintze
    Replies:
    0
    Views:
    292
    Clemens Hintze
    Nov 7, 2005
Loading...

Share This Page