Reputation: 263
In the dusty corners of a code base I work on, I've come across a class hierarchy that looks like this:
class Base1
{
int base1;
};
class Base2
{
int base2;
};
template <typename T> class A : public Base1
{
T _specialT;
};
template <> class A<int> : public Base2
{
int _special;
};
The use of Base2 in the specialization of A is something that surprised me. I've been searching around to understand exactly what it means, haven't been able to find any examples or discussions of this sort of design.
It seems to me that what this does is cause A to inherit from both Base1 and Base2 while other uses of A that are not specialized will inherit from only Base1. That leaves me with a couple of questions:
Upvotes: 4
Views: 782
Reputation: 24576
Keep in mind that different instantiations of class templates are different, independent classes. Specializations of templates do not add things to the general case, they replace it completely.
Thus, A<int>
is a class that derives from Base2
and has one int member named _special
, A<double>
and A<char>
are two independent, different classes that both happen to derive from Base1
and each have one member of type double and char, respectively, named _specialT
.
So:
Base1
on an A<int>
(or use the _specialT
member), getting compiler errors because he did not see the specialization. A very popular example is the specialization of std::vector<bool>
in the standard wich behaves differently from the "normal" std::vector
and is widely considered broken.This pattern (specializations deriving from different bases) is often used in Template Metaprogramming. A (very) simple example:
template <class T>
struct is_int_or_double : std::false_type
{};
template <>
struct is_int_or_double<int> : std::true_type //another base class!
{};
template <>
struct is_int_or_double<double> : std::true_type //another base class!
{};
Upvotes: 2
Reputation: 55395
Base1
and only the <int>
specialization inherits from Base2
(and from Base2
only).Not knowing the context where this is used, I can't answer 2. or 3.
You can often see specializations deriving from different types in template meta-programming. For example:
template<typename T, typename U>
struct is_same : std::false_type {};
template<typename T>
struct is_same<T,T> : std::true_type {};
It's perfectly valid thing to do. Whether it is a good thing to do depends entirely on the problem being solved.
Upvotes: 4
Reputation: 71909
A specialization of a template is completely independent, code-wise, from the normal case. So A<int>
will not derive from both Base1
and Base2
, just from Base2
.
There are certainly cases where specializations are good design. Whether this is one is not possible to tell from your abstracted example, of course.
Upvotes: 2