Why is the specialization S in A legal and S in B not?
( if B is not commented out ) GCC 4.8.1: error: explicit specialization in non-namespace scope ‘class B’
#include <type_traits>
#include <iostream>
class Y {};
class X {};
struct A {
template<class T, class = void>
class S;
template<class T>
struct S < T, typename std::enable_if< std::is_same< Y, T >::value >::type >
{
int i = 0;
};
template<class T>
struct S < T, typename std::enable_if< std::is_same< X, T >::value >::type >
{
int i = 1;
};
};
/*
class B
{
template<class T>
class S;
template<>
class S < Y > {};
template<>
class S < X > {};
};
*/
int main()
{
A::S< X > asd;
std::cout << asd.i << std::endl;
}
The comments by @jrok pretty much explains your compiler error. Nested classes in general, and nested class templates in particular, are a dusty corner of the language that you can easily avoid (taking to heart Sutter's advice "Write what you know and know what you write").
Simply make a namespace detail
to define your class templates SA
and SB
and their specializations and then define a nested template type alias S
inside both A
and B
namespace detail {
template<class T, class = void>
class SA;
template<class T>
struct SA < T, typename std::enable_if< std::is_same< Y, T >::value >::type >
{
int i = 0;
};
template<class T>
struct SA < T, typename std::enable_if< std::is_same< X, T >::value >::type >
{
int i = 1;
};
template<class T>
class SB;
template<>
class SB < Y > {};
template<>
class SB < X > {};
}
struct A
{
template<class T>
using S = detail::SA<T>;
};
struct B
{
template<class T>
using S = detail::SB<T>;
};
Granted, for this case it might seem overkill, but if you ever want to make A
and B
class templates themselves, and specialize A
and B
, then you can only specialize the nested class templates if you also specialize the enclosing class. In short: just avoid these issues altogether by an extra level of compile-time indirection.