Kirill Kobelev
Kirill Kobelev

Reputation: 10557

Explicit specialization of non-class, non-function members of a class template

Look at the code:

template <class x> struct Foo
{
    int getX(x *p) { return(0); }
    enum E12 { a };
};

template <> int Foo<int>::getX(int*)
{
    return(-15);
}

template <> enum Foo<int>::E12
{
    a, b, c
}

As it was discussed in Cannot overload function, the first specialization is legal and even works in MSVC. While the second specialization for enum does not even want to compile, saying "error C2988: unrecognizable template declaration/definition".

It seems to me that C++ is making relaitively unlogical exception for methods. Enum is just an example. The same thing can be applied to member classes, typedefs, etc.

I will be happy is some body will comment on this.

Upvotes: 1

Views: 556

Answers (1)

Potatoswatter
Potatoswatter

Reputation: 137940

This is a very obscure new feature of C++11. File a bug report with Microsoft, although it is unlikely it will be given priority as almost nobody is aware this is allowed. The correct syntax would be

template <class x> struct Foo
{
    int getX(x *p) { return(0); }
    enum E12 { a };
};
 
template <> int Foo<int>::getX(int*)
{
    return(-15);
}
 
template <> enum Foo<int>::E12
{
    a, b, c
};

I've filed a bug with GCC. Can someone test on recent Clang?


In C++03, only classes and functions may be explicitly specialized. From the standard, C++03 14.7.3/1:

An explicit specialization of any of the following:

  • function template
  • class template
  • member function of a class template
  • static data member of a class template
  • member class of a class template
  • member class template of a class or class template
  • member function template of a class or class template

can be declared by a declaration introduced by template<>

A member enum is not such a case. (Generally speaking, an enum type is always defined only once at its first declaration.)

To obtain a templated enum or typedef, you can wrap it in a class template. In your case, it would be a member class template of Foo. Such a construct is called a metafunction.

C++11 also has alias templates, which are like templated typedefs, but they cannot be explicitly specialized.


The policy of only allowing classes and functions to be specialized, and then allowing such templates to encapsulate other things like enum and typedef, seems more consistent to me than allowing direct specialization of enum. But, perhaps the language is going in your preferred direction.

Upvotes: 1

Related Questions