[temp.expl.spec]

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

## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#temp.expl.spec)

### 13.9.4 Explicit specialization [temp.expl.spec]

[1](#1)

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

An explicit specialization of any of the following:

- [(1.1)](#1.1)

function template

- [(1.2)](#1.2)

class template

- [(1.3)](#1.3)

variable template

- [(1.4)](#1.4)

member function of a class template

- [(1.5)](#1.5)

static data member of a class template

- [(1.6)](#1.6)

member class of a class template

- [(1.7)](#1.7)

member enumeration of a class template

- [(1.8)](#1.8)

member class template of a class or class template

- [(1.9)](#1.9)

member function template of a class or class template

can be declared by a declaration introduced bytemplate<>;
that is:

[explicit-specialization:](#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]")  
template < > [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")

[*Example [1](#example-1)*: template<class T> class stream;

template<> class stream<char> { /* ... */ }; // #1template<class T> class Array { /* ... */ };template<class T> void sort(Array<T>& v) { /* ... */ }template<> void sort<int>(Array<int>&); // #2template<> void sort(Array<char*>&); // #3 template argument is deduced ([[temp.arg.explicit]](temp.arg.explicit "13.10.2 Explicit template argument specification"))

Given these declarations,
#1 will be used as the definition of streams ofchars;
other streams will be handled by class template specializations instantiated
from the class template[.](#1.sentence-2)

Similarly,
#2 will be used as the sort function for arguments of
type Array<int> and
#3 will be used for arguments
of typeArray<char*>;
otherArray types will be sorted by functions generated from the function template[.](#1.sentence-3)

â *end example*]

[2](#2)

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

The [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in an [*explicit-specialization*](#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") shall not be an [*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")[.](#2.sentence-1)

An explicit specialization shall not use
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers"))
other than thread_local[.](#2.sentence-2)

[3](#3)

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

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

[4](#4)

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

An explicit specialization does not introduce a name ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))[.](#4.sentence-1)

A declaration of a function template, class template, or variable template being explicitly
specialized shall be reachable from the declaration of
the explicit specialization[.](#4.sentence-2)

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

A declaration, but not a definition of the template is needed[.](#4.sentence-3)

â *end note*]

The definition of a class or class template shall be reachable from the
declaration of an explicit specialization for a member template of the class
or class template[.](#4.sentence-4)

[*Example [2](#example-2)*: template<> class X<int> { /* ... */ }; // error: X not a templatetemplate<class T> class X;

template<> class X<char*> { /* ... */ }; // OK, X is a template â *end example*]

[5](#5)

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

A member function, a member function template, a member class,
a member enumeration, a
member class template,
a static data member, or a static data member template of a class template
may be explicitly specialized for a class specialization that is implicitly
instantiated;
in this case, the definition of the class template shall
be reachable from the explicit specialization for the member of the class
template[.](#5.sentence-1)

If such an explicit specialization for the member of a class template names an
implicitly-declared special member function ([[special]](special "11.4.4 Special member functions")),
the program is ill-formed[.](#5.sentence-2)

[6](#6)

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

A member of an explicitly specialized class is not implicitly
instantiated from the member declaration of the class template;
instead, the member of the class template specialization shall itself be
explicitly defined if its definition is required[.](#6.sentence-1)

The definition of the class template explicit specialization
shall be reachable from the definition of any member of it[.](#6.sentence-2)

The definition of an explicitly specialized class is unrelated to the
definition of a generated specialization[.](#6.sentence-3)

That is, its members need
not have the same names, types, etc. as the members of a generated
specialization[.](#6.sentence-4)

Members of an explicitly specialized
class template are defined in the same manner as members of normal classes, and
not using the template<> syntax[.](#6.sentence-5)

The same is true when defining a member of an explicitly specialized member
class[.](#6.sentence-6)

However, template<> is used in defining a member of an explicitly
specialized member class template that is specialized as a class template[.](#6.sentence-7)

[*Example [3](#example-3)*: template<class T> struct A {struct B { }; template<class U> struct C { };};

template<> struct A<int> {void f(int);};

void h() { A<int> a;
 a.f(16); // A<int>​::​f must be defined somewhere}// template<> not used for a member of an explicitly specialized class templatevoid A<int>::f(int) { /* ... */ }template<> struct A<char>::B {void f();};// template<> also not used when defining a member of an explicitly specialized member classvoid A<char>::B::f() { /* ... */ }template<> template<class U> struct A<char>::C {void f();};// template<> is used when defining a member of an explicitly specialized member class template// specialized as a class templatetemplate<>template<class U> void A<char>::C<U>::f() { /* ... */ }template<> struct A<short>::B {void f();};template<> void A<short>::B::f() { /* ... */ } // error: template<> not permittedtemplate<> template<class U> struct A<short>::C {void f();};template<class U> void A<short>::C<U>::f() { /* ... */ } // error: template<> required â *end example*]

[7](#7)

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

If a template, a member template or a member of a class template is explicitly
specialized, a declaration of that specialization shall be reachable from
every use of
that specialization that would cause an implicit instantiation to take place,
in every translation unit in which such a use occurs;
no diagnostic is required[.](#7.sentence-1)

If the program does not provide a definition for an explicit specialization and
either the specialization is used in a way that would cause an implicit
instantiation to take place or the member is a virtual member function,
the program is ill-formed, no diagnostic required[.](#7.sentence-2)

An implicit instantiation is never generated for an explicit specialization
that is declared but not defined[.](#7.sentence-3)

[*Example [4](#example-4)*: class String { };template<class T> class Array { /* ... */ };template<class T> void sort(Array<T>& v) { /* ... */ }void f(Array<String>& v) { sort(v); // use primary template sort(Array<T>&), T is String}template<> void sort<String>(Array<String>& v); // error: specialization after use of primary templatetemplate<> void sort<>(Array<char*>& v); // OK, sort<char*> not yet usedtemplate<class T> struct A {enum E : T; enum class S : T;};template<> enum A<int>::E : int { eint }; // OKtemplate<> enum class A<int>::S : int { sint }; // OKtemplate<class T> enum A<T>::E : T { eT };template<class T> enum class A<T>::S : T { sT };template<> enum A<char>::E : char { echar }; // error: A<char>​::​E was instantiated// when A<char> was instantiatedtemplate<> enum class A<char>::S : char { schar }; // OK â *end example*]

[8](#8)

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

The placement of explicit specialization declarations for function templates, class
templates, variable templates,
member functions of class templates, static data members of class
templates, member classes of class templates, member enumerations of class
templates, member class templates of class
templates, member function templates of class templates,
static data member templates of class templates,
member functions of
member templates of class templates, member functions of member templates of
non-template classes,
static data member templates of non-template classes,
member function templates of member classes of class
templates, etc., and the placement of partial specialization declarations
of class templates, variable templates,
member class templates of non-template classes,
static data member templates of non-template classes, member
class templates of class templates, etc., can affect whether a program is
well-formed according to the relative positioning of the explicit specialization
declarations and their points of instantiation in the translation unit as
specified above and below[.](#8.sentence-1)

When writing a specialization, be careful about its location;
or to make it compile will be such a trial as to kindle its self-immolation[.](#8.sentence-2)

[9](#9)

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

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

A class template explicit specialization that has been declared but
not defined can be used exactly like other
incompletely-defined classes ([[basic.types]](basic.types "6.9 Types"))[.](#9.sentence-1)

[*Example [5](#example-5)*: template<class T> class X; // X is a class templatetemplate<> class X<int>;

X<int>* p; // OK, pointer to declared class X<int> X<int> x; // error: object of incomplete class X<int> â *end example*]

â *end note*]

[10](#10)

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

[*Note [3](#note-3)*:

An explicit specialization of a constrained template needs
to satisfy that template's associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#10.sentence-1)

The satisfaction of constraints is determined
when forming the template name of an explicit specialization
in which all template arguments are specified ([[temp.names]](temp.names "13.3 Names of template specializations")),
or, for explicit specializations of function templates,
during template argument deduction ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration"))
when one or more trailing template arguments are left unspecified[.](#10.sentence-2)

â *end note*]

[11](#11)

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

A function with the same name as a template and a type that exactly matches that
of a template specialization is not an explicit specialization ([[temp.fct]](temp.fct "13.7.7 Function templates"))[.](#11.sentence-1)

[12](#12)

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

Whether an explicit specialization of a function or variable template
is inline, constexpr, constinit, or consteval
is determined by the explicit specialization and
is independent of those properties of the template[.](#12.sentence-1)

Similarly,
attributes and [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")*s* appearing in the declaration of a template
have no effect on an explicit specialization of that template[.](#12.sentence-2)

[*Example [6](#example-6)*: template<class T> void f(T) { /* ... */ }template<class T> inline T g(T) { /* ... */ }template<> inline void f<>(int) { /* ... */ } // OK, inlinetemplate<> int g<>(int) { /* ... */ } // OK, not inlinetemplate<typename> [[noreturn]] void h([[maybe_unused]] int i);template<> void h<int>(int i) {// Implementations are expected not to warn that the function returns// but can warn about the unused parameter.} â *end example*]

[13](#13)

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

An explicit specialization of a static data member of a template
or an explicit specialization of a static data member template is a
definition if the declaration includes an initializer;
otherwise, it is a declaration[.](#13.sentence-1)

[*Note [4](#note-4)*:

The definition of a static data member of a template
for which default-initialization is desired
can use functional cast notation ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")):template<> X Q<int>::x; // declarationtemplate<> X Q<int>::x (); // error: declares a functiontemplate<> X Q<int>::x = X(); // definition

â *end note*]

[14](#14)

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

A member or a member template of a class template may be explicitly specialized
for a given implicit instantiation of the class template, even if the member
or member template is defined in the class template definition[.](#14.sentence-1)

An explicit specialization of a member or member template is specified using the
syntax for explicit specialization[.](#14.sentence-2)

[*Example [7](#example-7)*: template<class T> struct A {void f(T); template<class X1> void g1(T, X1); template<class X2> void g2(T, X2); void h(T) { }};

// specializationtemplate<> void A<int>::f(int);

// out of class member template definitiontemplate<class T> template<class X1> void A<T>::g1(T, X1) { }// member template specializationtemplate<> template<class X1> void A<int>::g1(int, X1);

// member template specializationtemplate<> template<>void A<int>::g1(int, char); // X1 deduced as chartemplate<> template<>void A<int>::g2<char>(int, char); // X2 specified as char// member specialization even if defined in class definitiontemplate<> void A<int>::h(int) { } â *end example*]

[15](#15)

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

A member or a member template may be nested within many enclosing class
templates[.](#15.sentence-1)

In an explicit specialization for such a member,
the member declaration shall be preceded by atemplate<> for each enclosing class template that is explicitly specialized[.](#15.sentence-2)

[*Example [8](#example-8)*: template<class T1> class A {template<class T2> class B {void mf(); };};template<> template<> class A<int>::B<double>;template<> template<> void A<char>::B<char>::mf(); â *end example*]

[16](#16)

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

In an explicit specialization declaration for a member of a class template or
a member template that appears in namespace scope,
the member template and some of its enclosing class templates may remain
unspecialized,
except that the declaration shall not explicitly specialize a class member
template if its enclosing class templates are not explicitly specialized
as well[.](#16.sentence-1)

In such an explicit specialization declaration, the keywordtemplate followed by a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") shall be provided instead of thetemplate<> preceding the explicit specialization declaration of the member[.](#16.sentence-2)

The types of the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* in the[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") shall be the same as those specified in the primary template definition[.](#16.sentence-3)

[*Example [9](#example-9)*: template <class T1> class A {template<class T2> class B {template<class T3> void mf1(T3); void mf2(); };};template <> template <class X>class A<int>::B {template <class T> void mf1(T); };template <> template <> template<class T>void A<int>::B<double>::mf1(T t) { }template <class Y> template <>void A<Y>::B<double>::mf2() { } // error: B<double> is specialized but// its enclosing class template A is not â *end example*]

[17](#17)

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

A specialization of a member function template, member class template,
or static data member template of
a non-specialized class template is itself a template[.](#17.sentence-1)

[18](#18)

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

An explicit specialization declaration shall not be a friend declaration[.](#18.sentence-1)

[19](#19)

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

Default function arguments shall not be specified in a declaration or
a definition for one of the following explicit specializations:

- [(19.1)](#19.1)

the explicit specialization of a function template;

- [(19.2)](#19.2)

the explicit specialization of a member function template;

- [(19.3)](#19.3)

the explicit specialization of a member function of a class template where
the class template specialization to which the member function specialization
belongs is implicitly instantiated[.](#19.sentence-1)
  [*Note [5](#note-5)*:
  Default function arguments can be specified in the declaration or
definition of a member function of a class template specialization that is
explicitly specialized[.](#19.3.sentence-2)
 â *end note*]
