472,126 Members | 1,557 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,126 software developers and data experts.

typedef of template classes are always default constructed?

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<ClassBCA;
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<cbCA;

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

Nov 7 '06 #1
12 2192
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<ClassBCA;
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<cbCA;

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

Nov 7 '06 #2

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<ClassBCA;
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<cbCA;

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.

Nov 7 '06 #3


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

Nov 8 '06 #4
du************@yahoo.dk wrote:
could anyone explain why the above program works if pointer is used ?
If a pointer is used where?

Cheers! --M

Nov 8 '06 #5

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<ClassBCA;
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<cbCA;

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.
Nov 8 '06 #6
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<ClassBCA;
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<cbCA;
>
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

Nov 8 '06 #7
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<ClassBCA;
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<cbCA;

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

Nov 8 '06 #8
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

Nov 8 '06 #9

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!

Nov 8 '06 #10

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<ClassBCA;
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<cbCA;
>
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;
}

Nov 8 '06 #11

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!

Nov 8 '06 #12

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!

Nov 8 '06 #13

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by jack | last post: by
31 posts views Thread by nikola | last post: by
7 posts views Thread by Gurikar | last post: by
7 posts views Thread by Tony Johansson | last post: by
5 posts views Thread by Alan Woodland | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.