g++ and subclass template specialization

V

vilarneto

Hello everyone,

Today I started to use template specializations in a project and
suddenly faced a curious problem. Following is a complete example
that shows the situation:

----------

class A {
};


template<class T>
class B : public A {
};


template<>
class B<int> {
};


int main(int argc, char *argv[]) {
A *a;
a = new B<double>;
a = new B<int>;
return 0;
}

----------

g++ 3.4.6, refuses to compile the 2nd assignment, issuing a "cannot
convert `B<int>*' to `A*' in assignment" error. However, under my
concepts B is a subclass of A (as expected, the compiler accepts the
1st assignment).

Is this a compiler bug or a language specification? Does anyone
suggests a portable workaround (other than avoid TS and subclass
B<int> as a nontemplate class C)?

C++ is really an interesting language... after 10+ years of daily
use, sometimes we find ourselves amused with something unexpected.
 
V

vilarneto

Nevermind. I didn't know that the subclassing statement should be
repeated when declaring the specialized template. This solved the
problem:

template<>
class B<int> : public A {
};

Also, it suggests that template specialization can break class
hierarchy. It's impressive.
 
A

Alf P. Steinbach

* (e-mail address removed):
Nevermind. I didn't know that the subclassing statement should be
repeated when declaring the specialized template. This solved the
problem:

template<>
class B<int> : public A {
};

Also, it suggests that template specialization can break class
hierarchy. It's impressive.

Specializations are completely unrelated classes at the type level.

A specialization doesn't inherit anything from the base template.

They are usually designed to be used /syntactically/ the same way,
capturing a kind of "concept": C++0x will introduce support for
declaring concepts, so that also the compiler knows a little about them,
but I'm not familiar with the details.
 
V

Victor Bazarov

Hello everyone,

Today I started to use template specializations in a project and
suddenly faced a curious problem. Following is a complete example
that shows the situation:

----------

class A {
};


template<class T>
class B : public A {
};


template<>
class B<int> {
};



int main(int argc, char *argv[]) {
A *a;
a = new B<double>;
a = new B<int>;
return 0;
}

----------

g++ 3.4.6, refuses to compile the 2nd assignment, issuing a "cannot
convert `B<int>*' to `A*' in assignment" error. However, under my
concepts B is a subclass of A (as expected, the compiler accepts the
1st assignment).

B is not a subclass of anything. B is a class template. B<int> is
Is this a compiler bug or a language specification?

It is not a compiler bug.
Does anyone
suggests a portable workaround (other than avoid TS and subclass
B<int> as a nontemplate class C)?

Huh?

template said:
C++ is really an interesting language... after 10+ years of daily
use, sometimes we find ourselves amused with something unexpected.

V
 
G

Greg Herlihy

Today I started to use template specializations in a project and
suddenly faced a curious problem. Following is a complete example
that shows the situation:

class A {
};


template<class T>
class B : public A {
};


template<>
class B<int> {
};


int main(int argc, char *argv[]) {
A *a;
a = new B<double>;
a = new B<int>;
return 0;
}

g++ 3.4.6, refuses to compile the 2nd assignment, issuing a "cannot
convert `B<int>*' to `A*' in assignment" error. However, under my
concepts B is a subclass of A (as expected, the compiler accepts the
1st assignment).

B<double> is a subclass of A - but due to the specialization, B<int> is not
a subclass of anything. To declare B<int> as a subclass of A, the
specialization for B<int> needs to be changed to this:

template <>
class B<int> : public A
{
};

In other words, B<int> is its own class template - and shares nothing with
the general B class template. So, if you want B<int> to have any of the same
base classes or members as the general B class template, you will have to be
sure that the B<int> specialization makes the same set of declarations as
Is this a compiler bug or a language specification? Does anyone
suggests a portable workaround (other than avoid TS and subclass
B<int> as a nontemplate class C)?

Declare B<int> exactly how you want B<int> to be declared - or move whatever
implementation that is to be shared with the general template into a common
(non-template) base class.
C++ is really an interesting language... after 10+ years of daily
use, sometimes we find ourselves amused with something unexpected.

I'm a bit surprised that after 10 years of C++, you would not have known how
class template specializations work.

Greg
 
V

vilarneto

A specialization doesn't inherit anything from the base template.

....which makes me wonder: is that possible to make specialized B<int>
a subclass of B<T=int>?

Since they are unrelated classes, as you said before, that kind of
subclassing should pose no problems... but I can't think of the
syntax for that.

I've tried an intermediate typedef, but it generated a compiler
error... OK, I recognize that this is confusing even for humans,
because it smells like recursion:

typedef B<int> C;

template<>
class B<int> : public C { // error: invalid use of undefined type
`class C'
};
 
V

vilarneto

I'm a bit surprised that after 10 years of C++, you would not have known how
class template specializations work.

Indeed, the starting question sounds silly because I was lacking a key
concept about the subject, sorry. It just happened that I never
needed coding template specializations before.

And thanks for the explanation.
 
V

vilarneto

I'm a bit surprised that after 10 years of C++, you would not have known how
class template specializations work.

Indeed, the starting question sounds silly because I was lacking a key
concept about the subject, sorry. It just happened that I never
needed coding template specializations before.

And thanks for the explanation.
 
A

Alf P. Steinbach

* (e-mail address removed):
...which makes me wonder: is that possible to make specialized B<int>
a subclass of B<T=int>?

Since they are unrelated classes, as you said before, that kind of
subclassing should pose no problems... but I can't think of the
syntax for that.

I've tried an intermediate typedef, but it generated a compiler
error... OK, I recognize that this is confusing even for humans,
because it smells like recursion:

typedef B<int> C;

template<>
class B<int> : public C { // error: invalid use of undefined type
`class C'
};

You'd need a declaration of B to make the compiler accept the typedef,
and then the specialization would effectively be

class B<int>: public B<int> { ... }

and a class can't inherit from itself.

However, you can do

#include <iostream>
#include <ostream>

template< typename T > struct S;

template<> struct S<double> { double d; S():d(1){} };
template<> struct S<int>: S<double> { int i; S():i(2){} };

int main()
{
S<int> o;
std::cout << o.d << " " << o.i << std::endl;
}
 
V

vilarneto

* (e-mail address removed):


There is no such thing as "B<T=int>".

No, of course: this was not syntatic. I meant "...to make
specialized `template<> class B<int>' a subclass of `template<class T>
class B<T> with T=int'". Also, your following explanation was very
clear about that, thank you.

And thanks to everyone.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top