Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > typedef of template classes are always default constructed?

Reply
Thread Tools

typedef of template classes are always default constructed?

 
 
aaragon
Guest
Posts: n/a
 
      11-07-2006
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

 
Reply With Quote
 
 
 
 
mlimber
Guest
Posts: n/a
 
      11-07-2006
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

 
Reply With Quote
 
 
 
 
Salt_Peter
Guest
Posts: n/a
 
      11-07-2006

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.

 
Reply With Quote
 
dudordoo123456@yahoo.dk
Guest
Posts: n/a
 
      11-08-2006


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

 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      11-08-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> could anyone explain why the above program works if pointer is used ?


If a pointer is used where?

Cheers! --M

 
Reply With Quote
 
aaragon
Guest
Posts: n/a
 
      11-08-2006

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.


 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      11-08-2006
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

 
Reply With Quote
 
aaragon
Guest
Posts: n/a
 
      11-08-2006
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

 
Reply With Quote
 
mlimber
Guest
Posts: n/a
 
      11-08-2006
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

 
Reply With Quote
 
aaragon
Guest
Posts: n/a
 
      11-08-2006

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!

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
typedef of template<T> x to member x in template class squarewave@blockhead.net C++ 1 02-20-2009 08:15 PM
CRTP-problem: How can the base class typedef a derived class' typedef? oor C++ 0 05-20-2008 12:39 PM
Extracting template types from a typedef'd template declaration Adam Nielsen C++ 3 10-19-2007 09:54 AM
types of classes in template classes lobequadrat@googlemail.com C++ 5 04-27-2007 05:33 PM
need for typedef for instances of template classes puzzlecracker C++ 1 09-16-2005 05:29 AM



Advertisments