Assuming you already added typename
as suggested by Nawaz.
The problem is exactly explained in the error message you encounter: "template parameter is not deducible in partial specialization B<T>::type*
. The problem is that B<T>::type
and T
is exactly the same for all types T
. Consider the following example:
class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)
X<MyClass*> obj1;
X<MyClass2*> obj2;
The result of line (*)
is a type MyClass2 which is essentially MyClass1
. So, obj1
and obj2
should be objects of the same class. Now, which version of template X
should they use?
If you would expect the specialised version of X
, tell me if the answer should be the same if line (*)
is removed (and obviously obj2
as well). Still obj1
should be the specialised version of X
as line (*)
has nothing to do with it.
But now we expect the compiler to detect that some type can be potentially declared as B<T>::type
although we never do this. We expect the compiler to verify all possible template instantiations to check if there is no strange typedef in one of them.
I hope this clarifies why such specialisation cannot be handled by the compiler.
An alternative that might help
I believe your problem could be attacked by creating a trait class for explicitly marking types that should be handled in a special way. Something like this:
template <bool v>
struct boolean_value {
static const bool value=v;
};
template <typename T>
struct is_my_interesting_type : public boolean_value<false> {};
class MyClass {
...
};
template <>
struct is_my_interesting_type<MyClass> : public boolean_value<true> {};
template <typename T, bool special>
class InternalX {
... //generic version of your template X
};
template <typename T>
class InternalX<T,true> {
... //special version of your template X
};
template <typename T>
class X : public InternalX<T,is_my_interesting_type<T>::value> {};
Also, you might be interesting how it is done in boost library, in particular Boost.Type_Traits