13 Templates [temp]

13.7 Template declarations [temp.decls]

13.7.6 Partial specialization [temp.spec.partial] General [temp.spec.partial.general]

A partial specialization of a template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization ([temp.spec.partial.match]).
A declaration of the primary template shall precede any partial specialization of that template.
A partial specialization shall be reachable from any use of a template specialization that would make use of the partial specialization as the result of an implicit or explicit instantiation; no diagnostic is required.
Two partial specialization declarations declare the same entity if they are partial specializations of the same template and have equivalent template-heads and template argument lists ([temp.over.link]).
Each partial specialization is a distinct template.
[Example 1: template<class T1, class T2, int I> class A { }; template<class T, int I> class A<T, T*, I> { }; template<class T1, class T2, int I> class A<T1*, T2, I> { }; template<class T> class A<int, T*, 5> { }; template<class T1, class T2, int I> class A<T1, T2*, I> { };
The first declaration declares the primary (unspecialized) class template.
The second and subsequent declarations declare partial specializations of the primary template.
— end example]
A partial specialization may be constrained ([temp.constr]).
[Example 2: template<typename T> concept C = true; template<typename T> struct X { }; template<typename T> struct X<T*> { }; // #1 template<C T> struct X<T> { }; // #2
Both partial specializations are more specialized than the primary template.
#1 is more specialized because the deduction of its template arguments from the template argument list of the class template specialization succeeds, while the reverse does not.
#2 is more specialized because the template arguments are equivalent, but the partial specialization is more constrained ([temp.constr.order]).
— end example]
The template argument list of a partial specialization is the template-argument-list following the name of the template.
A partial specialization may be declared in any scope in which the corresponding primary template may be defined ([dcl.meaning], [class.mem], [temp.mem]).
[Example 3: template<class T> struct A { struct C { template<class T2> struct B { }; template<class T2> struct B<T2**> { }; // partial specialization #1 }; }; // partial specialization of A<T>​::​C​::​B<T2> template<class T> template<class T2> struct A<T>::C::B<T2*> { }; // #2 A<short>::C::B<int*> absip; // uses partial specialization #2 — end example]
Partial specialization declarations do not introduce a name.
Instead, when the primary template name is used, any reachable partial specializations of the primary template are also considered.
[Note 1:
One consequence is that a using-declaration which refers to a class template does not restrict the set of partial specializations that are found through the using-declaration.
— end note]
[Example 4: namespace N { template<class T1, class T2> class A { }; // primary template } using N::A; // refers to the primary template namespace N { template<class T> class A<T, T*> { }; // partial specialization } A<int,int*> a; // uses the partial specialization, which is found through the using-declaration // which refers to the primary template — end example]
A non-type argument is non-specialized if it is the name of a non-type parameter.
All other non-type arguments are specialized.
Within the argument list of a partial specialization, the following restrictions apply:
  • The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the partial specialization.
    [Example 5: template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error — end example]
  • The partial specialization shall be more specialized than the primary template ([temp.spec.partial.order]).
  • The template parameter list of a partial specialization shall not contain default template argument values.128
  • An argument shall not contain an unexpanded pack.
    If an argument is a pack expansion ([temp.variadic]), it shall be the last argument in the template argument list.
The usual access checking rules do not apply to non-dependent names used to specify template arguments of the simple-template-id of the partial specialization.
[Note 2:
The template arguments can be private types or objects that would normally not be accessible.
Dependent names cannot be checked when declaring the partial specialization, but will be checked when substituting into the partial specialization.
— end note]
There is no context in which they would be used.