[temp.spec.partial]

# 13 Templates [[temp]](./#temp)

## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial)

### 13.7.6 Partial specialization [temp.spec.partial]

#### [13.7.6.1](#general) General [[temp.spec.partial.general]](temp.spec.partial.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3655)

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]](#match "13.7.6.2 Matching of partial specializations"))[.](#general-1.sentence-1)

A declaration of the primary template shall precede
any partial specialization of
that template[.](#general-1.sentence-2)

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[.](#general-1.sentence-3)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3668)

Two partial specialization declarations declare the same entity
if they are partial specializations of the same template and have equivalent[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* and template argument lists ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#general-2.sentence-1)

Each partial specialization is a distinct template[.](#general-2.sentence-2)

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3674)

[*Example [1](#general-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[.](#general-3.sentence-1)

The second and subsequent declarations declare partial specializations of
the primary template[.](#general-3.sentence-2)

â *end example*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3689)

A partial specialization may be constrained ([[temp.constr]](temp.constr "13.5 Template constraints"))[.](#general-4.sentence-1)

[*Example [2](#general-example-2)*: template<typename T> concept C = true;

template<typename T> struct X { };template<typename T> struct X<T*> { }; // #1template<C T> struct X<T> { }; // #2

Both partial specializations are more specialized than the primary template[.](#general-4.sentence-2)

#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[.](#general-4.sentence-3)

#2 is more specialized because the template arguments are equivalent,
but the partial specialization is more constrained ([[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints"))[.](#general-4.sentence-4)

â *end example*]

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3707)

The template argument list of a partial specialization is
the [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") following the name of the template[.](#general-5.sentence-1)

[6](#general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3711)

A partial specialization may be declared in any
scope in which the corresponding primary template
may be defined ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"), [[class.mem]](class.mem "11.4 Class members"), [[temp.mem]](temp.mem "13.7.3 Member templates"))[.](#general-6.sentence-1)

[*Example [3](#general-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*]

[7](#general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3732)

Partial specialization declarations do not introduce a name[.](#general-7.sentence-1)

Instead, when the primary template name is used, any reachable partial
specializations of the primary template are also considered[.](#general-7.sentence-2)

[*Note [1](#general-note-1)*:

One consequence is
that a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") which refers to a class template does not restrict the set of partial specializations
that are found through the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")[.](#general-7.sentence-3)

â *end note*]

[*Example [4](#general-example-4)*: namespace N {template<class T1, class T2> class A { }; // primary template}using N::A; // refers to the primary templatenamespace 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*]

[8](#general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3759)

A constant template argument is non-specialized if it is the name of a constant
template parameter[.](#general-8.sentence-1)

All other constant template arguments are specialized[.](#general-8.sentence-2)

[9](#general-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3764)

Within the argument list of a partial specialization,
the following restrictions apply:

- [(9.1)](#general-9.1)

  The type of a template parameter corresponding to a specialized constant template
argument shall not be dependent on a parameter of the partial specialization[.](#general-9.1.sentence-1)
  [*Example [5](#general-example-5)*: template <class T, T t> struct C {};template <class T> struct C<T, 1>; // errortemplate< int X, int (*array_ptr)[X] > class A {};int array[5];template< int X > class A<X,&array> { }; // error â *end example*]

- [(9.2)](#general-9.2)

  The partial specialization shall be more specialized than the primary
template ([[temp.spec.partial.order]](#order "13.7.6.3 Partial ordering of partial specializations"))[.](#general-9.2.sentence-1)

- [(9.3)](#general-9.3)

  The template parameter list of a partial specialization shall not contain default
template argument values[.](#general-9.3.sentence-1)[114](#footnote-114 "There is no context in which they would be used.")

- [(9.4)](#general-9.4)

  An argument shall not contain an unexpanded pack[.](#general-9.4.sentence-1)
  If
an argument is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), it shall be
the last argument in the template argument list[.](#general-9.4.sentence-2)

[10](#general-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3797)

The usual access checking rules do not apply to non-dependent names
used to specify template arguments of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") of the partial specialization[.](#general-10.sentence-1)

[*Note [2](#general-note-2)*:

The template arguments can be private types or
objects that would normally not be accessible[.](#general-10.sentence-2)

Dependent names cannot be checked when declaring the partial specialization,
but will be checked when substituting into the partial specialization[.](#general-10.sentence-3)

â *end note*]

[114)](#footnote-114)[114)](#footnoteref-114)

There is no context in which they would be used[.](#footnote-114.sentence-1)

#### [13.7.6.2](#match) Matching of partial specializations [[temp.spec.partial.match]](temp.spec.partial.match)

[1](#match-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3810)

When a template is used in a context that requires an instantiation of
the template,
it is necessary to determine whether the instantiation is to be generated
using the primary template or one of the partial specializations[.](#match-1.sentence-1)

This is done by matching the template arguments of the template
specialization with the template argument lists of the partial
specializations[.](#match-1.sentence-2)

- [(1.1)](#match-1.1)

  If exactly one matching partial specialization is found, the instantiation is
generated from that partial specialization[.](#match-1.1.sentence-1)

- [(1.2)](#match-1.2)

  If more than one matching partial specialization is found,
the partial order rules ([[temp.spec.partial.order]](#order "13.7.6.3 Partial ordering of partial specializations")) are used to determine
whether one of the partial specializations is more specialized than the
others[.](#match-1.2.sentence-1)
  If such a partial specialization exists,
the instantiation is generated from that partial specialization;
otherwise, the use of the template is ambiguous and the program is ill-formed[.](#match-1.2.sentence-2)

- [(1.3)](#match-1.3)

  If no matches are found, the instantiation is generated from the
primary template[.](#match-1.3.sentence-1)

[2](#match-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3836)

A partial specialization matches a given actual template argument
list if the template arguments of the partial specialization can be[deduced](temp.deduct "13.10.3 Template argument deduction [temp.deduct]") from the actual template argument list,
and the deduced template arguments satisfy the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") of the partial specialization, if any[.](#match-2.sentence-1)

[*Example [1](#match-example-1)*: template<class T1, class T2, int I> class A { }; // #1template<class T, int I> class A<T, T*, I> { }; // #2template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3template<class T> class A<int, T*, 5> { }; // #4template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 â *end example*]

[*Example [2](#match-example-2)*: template<typename T> concept C = requires (T t) { t.f(); };

template<typename T> struct S { }; // #1template<C T> struct S<T> { }; // #2struct Arg { void f(); };

S<int> s1; // uses #1; the constraints of #2 are not satisfied S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized â *end example*]

[3](#match-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3871)

If the template arguments of a partial specialization cannot be deduced
because of the structure of its [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") and the [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),
the program is ill-formed[.](#match-3.sentence-1)

[*Example [3](#match-example-3)*: template <int I, int J> struct A {};template <int I> struct A<I+5, I*2> {}; // errortemplate <int I> struct A<I, I> {}; // OKtemplate <int I, int J, int K> struct B {};template <int I> struct B<I, I*2, 2> {}; // OK â *end example*]

[4](#match-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3888)

In a name that refers to a specialization of a class or variable template
(e.g., A<int, int, 1>),
the argument list shall match the template parameter list of the primary
template[.](#match-4.sentence-1)

The template arguments of a partial specialization are deduced from the arguments
of the primary template[.](#match-4.sentence-2)

#### [13.7.6.3](#order) Partial ordering of partial specializations [[temp.spec.partial.order]](temp.spec.partial.order)

[1](#order-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3898)

For two partial specializations,
the first is [*more specialized*](temp.deduct.partial#def:more_specialized "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]") than the second if, given the following
rewrite to two function templates, the first function template is more
specialized than the second according to the [ordering rules for function
templates](temp.func.order "13.7.7.3 Partial ordering of function templates [temp.func.order]"):

- [(1.1)](#order-1.1)

  Each of the two
function templates has the same template parameters
and [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained declarations [temp.constr.decl]") as the corresponding partial specialization[.](#order-1.1.sentence-1)

- [(1.2)](#order-1.2)

  Each function template
has a single function parameter
whose type is a class template specialization where the template arguments
are the corresponding template parameters from the function template
for each template argument
in the [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") of the partial specialization[.](#order-1.2.sentence-1)

[2](#order-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3922)

[*Example [1](#order-example-1)*: template<int I, int J, class T> class X { };template<int I, int J> class X<I, J, int> { }; // #1template<int I> class X<I, I, int> { }; // #2template<int I0, int J0> void f(X<I0, J0, int>); // Atemplate<int I0> void f(X<I0, I0, int>); // Btemplate <auto v> class Y { };template <auto* p> class Y<p> { }; // #3template <auto** pp> class Y<pp> { }; // #4template <auto* p0> void g(Y<p0>); // Ctemplate <auto** pp0> void g(Y<pp0>); // D

According to the ordering rules for function templates,
the function template*B* is more specialized than the function template*A* and
the function template*D* is more specialized than the function template*C*[.](#order-2.sentence-1)

Therefore, the partial specialization #2
is more specialized than the partial specialization #1
and the partial specialization #4
is more specialized than the partial specialization #3[.](#order-2.sentence-2)

â *end example*]

[*Example [2](#order-example-2)*: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.f(); };

template<typename T> class S { };template<C T> class S<T> { }; // #1template<D T> class S<T> { }; // #2template<C T> void f(S<T>); // Atemplate<D T> void f(S<T>); // B

The partial specialization #2 is more specialized than #1
because B is more specialized than A[.](#order-2.sentence-3)

â *end example*]

#### [13.7.6.4](#member) Members of class template partial specializations [[temp.spec.partial.member]](temp.spec.partial.member)

[1](#member-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3973)

The members of the class template partial specialization are
unrelated to the members of the primary template[.](#member-1.sentence-1)

Class template partial specialization members that are used in a way that
requires a definition shall be defined; the definitions of members of the
primary template are never used as definitions for members of a class
template partial specialization[.](#member-1.sentence-2)

An explicit specialization of a member of a class template partial
specialization is declared in the same way as an explicit specialization of
a member of the primary template[.](#member-1.sentence-3)

[*Example [1](#member-example-1)*: // primary class templatetemplate<class T, int I> struct A {void f();};

// member of primary class templatetemplate<class T, int I> void A<T,I>::f() { }// class template partial specializationtemplate<class T> struct A<T,2> {void f(); void g(); void h();};

// member of class template partial specializationtemplate<class T> void A<T,2>::g() { }// explicit specializationtemplate<> void A<char,2>::h() { }int main() { A<char,0> a0;
 A<char,2> a2;
 a0.f(); // OK, uses definition of primary template's member a2.g(); // OK, uses definition of partial specialization's member a2.h(); // OK, uses definition of explicit specialization's member a2.f(); // error: no definition of f for A<T,2>; the primary template is not used here} â *end example*]

[2](#member-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4017)

If a member template of a class template is partially specialized,
the member template partial specializations are member templates of
the enclosing class template;
if the enclosing class template is instantiated ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation"), [[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")),
a declaration for every member template partial specialization is also
instantiated as part of creating the members of the class template
specialization[.](#member-2.sentence-1)

If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template,
the partial specializations of the member template are ignored for this
specialization of the enclosing class template[.](#member-2.sentence-2)

If a partial specialization of the member template is explicitly specialized
for a given (implicit) specialization of the enclosing class template,
the primary member template and its other partial specializations are
still considered for this specialization of the enclosing class template[.](#member-2.sentence-3)

[*Example [2](#member-example-2)*: template<class T> struct A {template<class T2> struct B {}; // #1template<class T2> struct B<T2*> {}; // #2};

template<> template<class T2> struct A<short>::B {}; // #3 A<char>::B<int*> abcip; // uses #2 A<short>::B<int*> absip; // uses #3 A<char>::B<int> abci; // uses #1 â *end example*]
