axe
axe

Reputation: 2371

template class template method specialization

Why does the following code fail to compile?

template <typename T>
struct X
{
    template <typename R>
    R default_value();
};

template <typename T>
int X<T>::default_value<int>()
{
    return -1;
}

it says

x.cpp:17:30: error: template-id ‘default_value<int>’ in declaration of primary template
x.cpp:17:5: error: prototype for ‘int X<T>::default_value()’ does not match any in class ‘X<T>’
x.cpp:13:7: error: candidate is: template<class T> template<class R> R X::default_value()

I also tried to do

template <typename T>
template <>
int X<T>::default_value<int>()
{
    return -1;
}

but this gives me another compilation error

prog.cpp:11: error: invalid explicit specialization before '>' token
prog.cpp:11: error: enclosing class templates are not explicitly specialized
prog.cpp:12: error: template-id 'default_value<int>' for 'int X<T>::default_value()' does not match any template declaration

I also tried doing the same for structures

template <typename T>
struct X
{
    template <typename R> struct default_value;
};

template <typename T>
template <>
struct X<T>::default_value<int>
{
    static int get() { return -1; }
};

same issue.

How to solve that?

Upvotes: 0

Views: 730

Answers (2)

Werner Erasmus
Werner Erasmus

Reputation: 4076

One cannot explicitly specialize member templates. Consider:

template <class T>
struct X
{
  template <class U> struct Y;
};

...Now (imagine we could do this):

template <class T>
  template <>
  struct X<T>::Y<int>
{};

...For X of which T are we explicitly specializing?

What if, after the point of definition of our explicit specialization, someone does this in one compilation unit...

void foo()
{
  X<int>::Y<int> xy;
}

... and then this in another...(valid code, btw).

template <>
  template<>
  struct X<int>::Y<int>
{};

void foo()
{
  X<int>::Y<int> xy;
}

... which would imply multiple definitions of the same class???

As mentioned previously, this is treated well here

Now, considering that the default value actually depends on the type T, perhaps one can get it from the type T.

template <class T>
struct X
{
  static T defaultValue(){ return T::defaultValue(); }
};

or better yet, one could change the behavior of defaultValue based on whether T has the member defaultValue.

Upvotes: 2

Naszta
Naszta

Reputation: 7734

template <typename T>
template <>
int X<T>::default_value<int>()
{
    return -1;
}

should be fine. Similar topic...

Upvotes: 0

Related Questions