Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I specialize the nested template member without specializing enclosing class template first?

Tags:

c++

templates

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 :)

Edit :

Andrei Alexandrescu's reply : "There's no particular reason - it's just a language rule."

like image 220
Mr.Anubis Avatar asked Feb 09 '12 21:02

Mr.Anubis


People also ask

What is explicit template specialization?

Explicit (full) specializationAllows customizing the template code for a given set of template arguments.

Can class template be nested?

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.

How do I restrict a template type in C++?

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.

What is the use of template specialization?

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.


1 Answers

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.)

like image 66
Kerrek SB Avatar answered Nov 15 '22 22:11

Kerrek SB