How is this specialization?

I watched this lecture where the following example is presented as a specialization (@ 29.43):

template<class T>
struct rank
{
    static const size_t value = 0u; 
}

// partial specialization
template<class U, size_t N>
struct rank<U[N]>
{
    static const size_t value = 1 + rank<U>::value; 
}

      

I would expect a compile error, complaining about incompatible struct declarations, and in the second, there are too many template parameters. How is this not a mistake above?

+3


source to share


2 answers


Specializations can have template parameters. Specializations with template parameters are called partial specializations.

template<class T>
struct rank { ...1 };

      

means rank<T>

- this is a class, and unless otherwise noted ...1

- this is a class definition.



template<class U, size_t N>
struct rank<U[N]> { ...2 };

      

- this is "otherwise specified": it means that if T

in rank<T>

can be written as U[N]

for some type U

and some constant N

, then ...2

- this is a class definition.

You would use it like rank<int[2]>

, which would use the second class definition with U = int

and N = 2

.

+10


source


This is not a mistake, because it is valid.

[C++11: 14.5.5/1]:

A main class template declaration is a name where the class template name is an identifier. A template declaration where the class template name is simple-template-id is a partial specialization of the class template named in simple-template-id. A partial specialization of a class template provides an alternative template definition that is used in place of the main definition when the arguments in the specialization match those specified in the partial specialization (14.5.5.1). [..]

There is no simple rule against it, and in fact the standard contains an example of exactly this scenario:

[C++11: 14.5.5/3]:

[Example:

template<class T1, class T2, int I> class A { };             // #1
template<class T, int I>            class A<T, T*, I> { };   // #2
template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
template<class T>                   class A<int, T*, 5> { }; // #4
template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5

      

The first declaration declares a primary (non-specialized) class. The second and subsequent declarations declare a partial specialization of the primary template. -end example]



The only limitation, which is even slightly related, is ironically closer (though not exactly) to the opposite of what you are claiming:

[C++11: 14.5.5/8]:

The following restrictions apply to the argument list of a template template partial specialization:

  • [..]
  • The specialization argument list does not have to be identical to the primary template's implicit argument list.
  • [..]

You would use primary and templated and partial specializations, for example:

int main()
{
    rank<char>   a;   // uses the primary
    rank<int[5]> b;   // uses the partial spec.
}

      

+4


source







All Articles