Here is the code :
template <typename T>
struct A
{
template <typename U>
struct B;
};
template <typename T> template <> // 0_o
struct A<T>::B<int> {};
I know I can't do this but I'm more interested to know logically Why can't I specialize the nested template member without specializing enclosing class template first?
I appreciate any help with logical explanation :)
Andrei Alexandrescu's reply : "There's no particular reason - it's just a language rule."
Explicit (full) specializationAllows customizing the template code for a given set of template arguments.
Member templates that are classes are referred to as nested class templates. Member templates that are functions are discussed in Member Function Templates. Nested class templates are declared as class templates inside the scope of the outer class. They can be defined inside or outside of the enclosing class.
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
This is called template specialization. Template allows us to define generic classes and generic functions and thus provide support for generic programming. Generic programming is an approach where generic data types are used as parameters in algorithms so that they work for variety of suitable data types.
Here's an idea based on Xeo's example: First, let's have our candidate primary template:
template <typename T> struct Foo
{
template <typename U> struct Bar { /* ... */ };
/* ... */
};
Now suppose we want to specialize the inner template, hypothetically:
template <typename T> template <> struct Foo<T>::Bar<bool> { /* ... */ }
// not actual C++!
But now suppose there are specializations of Foo
:
template <> struct Foo<int>
{
template <typename U> struct Bar { /* ... */ };
};
template <> struct Foo<char>
{
template <typename U> U Bar() { }
};
Now what if you want to use Foo<S>::Bar<bool>
? When S = char
, we cannot use the inner specialization, because it makes no sense. But if we disallow the inner specialization for all specializations of the outer template, then Foo<int>::Bar<bool>
isn't specialized, while Foo<float>::Bar<bool>
will be specialized. So our hypothetical inner specialization does not apply to Foo<int>
, even though one might have expected that it should.
This isn't a real technical reason that it can't be done, but just an illustration how it would have very unexpected behaviour. (For instance, imagine the specialization for int
was written later, and existing code depended on the inner specialization.)
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