Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template partial specialization

Tags:

c++

templates

Would any one knows according to what rules code below doesn't compile?

template <class T>
struct B
{
    typedef T type;
};

template<class T>
struct X
{
};
template<class T>
struct X<B<T>::type*>//HERE I'M PARTIALLY SPECIALIZING (WELL, TRYING TO...)
{
};

Please see comment inside the code.

like image 870
There is nothing we can do Avatar asked Mar 06 '11 15:03

There is nothing we can do


2 Answers

How do you think that will work? The compiler will look to see if there is a class T somewhere that has a typedef "type" to your class?

It just won't. Even though it's a pointer.

Remember that presumably your B template is presumably specialised in places so that type is not always T*, but it can't deduce it with reverse engineering.

For those who did not understand my answer fully, what you are asking the compiler to do is find a class U such that B::type is the class you pass in as a parameter.

class Foo;
class Bar;

template<> struct B<Foo>
{
  typedef int type;
};

template<> struct B<Bar>
{
  typedef int type;
};

X<int*> // ambiguous, T is Foo or Bar?

It is difficult to know exactly why you are trying to do what you are. You can do a partial specialization on all pointers and then a total specialization on specific pointers, which could be implement in terms of another template.

like image 187
CashCow Avatar answered Nov 14 '22 23:11

CashCow


You need to use typename keyword as,

template<class T>
struct X<typename B<T>::type*>
{
};

It's because B<T>::type is a dependent name. So typename is required!

--

EDIT:

Even after putting typename, it isn't compiling. I think it's because deduction of type T in B<T> from X<U> is difficult, or possibly impossible, for the compiler. So I believe its non-deduced context.

See a similar example here and the discussion:

Template parameters in non-deduced contexts in partial specializations


However, if you change the specialization to this:

template<class T>
struct X<B<T> >
{
};

Then it becomes the deducible context, and so would compile.

like image 42
Nawaz Avatar answered Nov 14 '22 23:11

Nawaz