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;
}
on coliru: B commented out
on coliru: with B (error)
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.
An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template.
What is the syntax to use explicit class specialization? Explanation: The class specialization is creation of explicit specialization of a generic class. We have to use template<> constructor for this to work. It works in the same way as with explicit function specialization.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With