13 Templates [temp]

13.9 Template instantiation and specialization [temp.spec]

13.9.1 General [temp.spec.general]

The act of instantiating a function, a variable, a class, a member of a class template, or a member template is referred to as template instantiation.
A function instantiated from a function template is called an instantiated function.
A class instantiated from a class template is called an instantiated class.
A member function, a member class, a member enumeration, or a static data member of a class template instantiated from the member definition of the class template is called, respectively, an instantiated member function, member class, member enumeration, or static data member.
A member function instantiated from a member function template is called an instantiated member function.
A member class instantiated from a member class template is called an instantiated member class.
A variable instantiated from a variable template is called an instantiated variable.
A static data member instantiated from a static data member template is called an instantiated static data member.
An explicit specialization may be declared for a function template, a variable template, a class template, a member of a class template, or a member template.
An explicit specialization declaration is introduced by template<>.
In an explicit specialization declaration for a variable template, a class template, a member of a class template, or a class member template, the variable or class that is explicitly specialized shall be specified with a simple-template-id.
In the explicit specialization declaration for a function template or a member function template, the function or member function explicitly specialized may be specified using a template-id.
[Example 1: template<class T = int> struct A { static int x; }; template<class U> void g(U) { } template<> struct A<double> { }; // specialize for T == double template<> struct A<> { }; // specialize for T == int template<> void g(char) { } // specialize for U == char // U is deduced from the parameter type template<> void g<int>(int) { } // specialize for U == int template<> int A<char>::x = 0; // specialize for T == char template<class T = int> struct B { static int x; }; template<> int B<>::x = 1; // specialize for T == int — end example]
An instantiated template specialization can be either implicitly instantiated ([temp.inst]) for a given argument list or be explicitly instantiated ([temp.explicit]).
A specialization is a class, variable, function, or class member that is either instantiated ([temp.inst]) from a templated entity or is an explicit specialization ([temp.expl.spec]) of a templated entity.
For a given template and a given set of template-arguments,
  • an explicit instantiation definition shall appear at most once in a program,
  • an explicit specialization shall be defined at most once in a program, as specified in [basic.def.odr], and
  • both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit specialization is reachable from the explicit instantiation.
An implementation is not required to diagnose a violation of this rule if neither declaration is reachable from the other.
The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer.
[Note 1: 
In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) can be private types or objects that would normally not be accessible.
— end note]
Each class template specialization instantiated from a template has its own copy of any static members.
[Example 2: template<class T> class X { static T s; }; template<class T> T X<T>::s = 0; X<int> aa; X<char*> bb;
X<int> has a static member s of type int and X<char*> has a static member s of type char*.
— end example]
If a function declaration acquired its function type through a dependent type without using the syntactic form of a function declarator, the program is ill-formed.
[Example 3: template<class T> struct A { static T t; }; typedef int function(); A<function> a; // error: would declare A<function>​::​t as a static member function — end example]

13.9.2 Implicit instantiation [temp.inst]

A template specialization E is a declared specialization if there is a reachable explicit instantiation definition ([temp.explicit]) or explicit specialization declaration ([temp.expl.spec]) for E, or if there is a reachable explicit instantiation declaration for E and E is not
[Note 1: 
An implicit instantiation in an importing translation unit cannot use names with internal linkage from an imported translation unit ([basic.link]).
— end note]
Unless a class template specialization is a declared specialization, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
[Note 2: 
In particular, if the semantics of an expression depend on the member or base class lists of a class template specialization, the class template specialization is implicitly generated.
For instance, deleting a pointer to class type depends on whether or not the class declares a destructor, and a conversion between pointers to class type depends on the inheritance relationship between the two classes involved.
— end note]
[Example 1: template<class T> class B { /* ... */ }; template<class T> class D : public B<T> { /* ... */ }; void f(void*); void f(B<int>*); void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); // instantiation of D<int> required: call f(B<int>*) B<char>* q = pp; // instantiation of D<char> required: convert D<char>* to B<char>* delete ppp; // instantiation of D<double> required } — end example]
If the template selected for the specialization ([temp.spec.partial.match]) has been declared, but not defined, at the point of instantiation ([temp.point]), the instantiation yields an incomplete class type ([basic.types.general]).
[Example 2: template<class T> class X; X<char> ch; // error: incomplete type X<char> — end example]
[Note 3: 
Within a template declaration, a local class or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments, noexcept-specifiers, and non-static data member initializers, if any, but not their type-constraints or requires-clauses).
As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared.
— end note]
The implicit instantiation of a class template specialization causes
  • the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
  • the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.
The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifiers of the class member functions.
[Example 3: template<class T> struct C { void f() { T x; } void g() = delete; }; C<void> c; // OK, definition of C<void>​::​f is not instantiated at this point template<> void C<int>::g() { } // error: redefinition of C<int>​::​g — end example]
However, for the purpose of determining whether an instantiated redeclaration is valid according to [basic.def.odr] and [class.mem], an instantiated declaration that corresponds to a definition in the template is considered to be a definition.
[Example 4: template<class T, class U> struct Outer { template<class X, class Y> struct Inner; template<class Y> struct Inner<T, Y>; // #1a template<class Y> struct Inner<T, Y> { }; // #1b; OK, valid redeclaration of #1a template<class Y> struct Inner<U, Y> { }; // #2 }; Outer<int, int> outer; // error at #2
Outer<int, int>​::​Inner<int, Y> is redeclared at #1b.
(It is not defined but noted as being associated with a definition in Outer<T, U>.)
#2 is also a redeclaration of #1a.
It is noted as associated with a definition, so it is an invalid redeclaration of the same partial specialization.
template<typename T> struct Friendly { template<typename U> friend int f(U) { return sizeof(T); } }; Friendly<char> fc; Friendly<float> ff; // error: produces second definition of f(U) — end example]
Unless a member of a templated class is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
Unless a function template specialization is a declared specialization, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
A function whose declaration was instantiated from a friend function definition is implicitly instantiated when it is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.
[Note 4: 
An inline function that is the subject of an explicit instantiation declaration is not a declared specialization; the intent is that it still be implicitly instantiated when odr-used ([basic.def.odr]) so that the body can be considered for inlining, but that no out-of-line copy of it be generated in the translation unit.
— end note]
[Example 5: template<class T> struct Z { void f(); void g(); }; void h() { Z<int> a; // instantiation of class Z<int> required Z<char>* p; // instantiation of class Z<char> not required Z<double>* q; // instantiation of class Z<double> not required a.f(); // instantiation of Z<int>​::​f() required p->g(); // instantiation of class Z<char> required, and // instantiation of Z<char>​::​g() required }
Nothing in this example requires class Z<double>, Z<int>​::​g(), or Z<char>​::​f() to be implicitly instantiated.
— end example]
Unless a variable template specialization is a declared specialization, the variable template specialization is implicitly instantiated when it is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program.
A default template argument for a variable template is implicitly instantiated when the variable template is referenced in a context that requires the value of the default argument.
The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function is needed for constant evaluation by an expression ([expr.const]), even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition.
[Example 6: template<typename T> constexpr int f() { return T::value; } template<bool B, typename T> void g(decltype(B ? f<T>() : 0)); template<bool B, typename T> void g(...); template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0})); template<bool B, typename T> void h(...); void x() { g<false, int>(0); // OK, B ? f<T>() : 0 is not potentially constant evaluated h<false, int>(0); // error, instantiates f<int> even though B evaluates to false and // list-initialization of int from int cannot be narrowing } — end example]
If the function selected by overload resolution can be determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
[Example 7: template <class T> struct S { operator int(); }; void f(int); void f(S<int>&); void f(S<float>); void g(S<int>& sr) { f(sr); // instantiation of S<int> allowed but not required // instantiation of S<float> allowed but not required }; — end example]
If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated ([temp.over]).
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class or static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
[Note 5: 
The instantiation of a generic lambda does not require instantiation of substatements of a constexpr if statement within its compound-statement unless the call operator template is instantiated.
— end note]
It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.
The use of a template specialization in a default argument or default member initializer shall not cause the template to be implicitly instantiated except where needed to determine the correctness of the default argument or default member initializer.
The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
Similarly, the use of a default member initializer in a constructor definition or an aggregate initialization causes specializations in the default member initializer to be instantiated.
If a templated function f is called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function template f used at that point, except that the scope in which a closure type is declared ([expr.prim.lambda.closure]) — and therefore its associated namespaces — remain as determined from the context of the definition for the default argument.
This analysis is called default argument instantiation.
The instantiated default argument is then used as the argument of f.
Each default argument is instantiated independently.
[Example 8: template<class T> void f(T x, T y = ydef(T()), T z = zdef(T())); class A { }; A zdef(A); void g(A a, A b, A c) { f(a, b, c); // no default argument instantiation f(a, b); // default argument z = zdef(T()) instantiated f(a); // error: ydef is not declared } — end example]
The noexcept-specifier of a function template specialization is not instantiated along with the function declaration; it is instantiated when needed ([except.spec]).
If such an noexcept-specifier is needed but has not yet been instantiated, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the noexcept-specifier is done as if it were being done as part of instantiating the declaration of the specialization at that point.
[Note 6: 
[temp.point] defines the point of instantiation of a template specialization.
— end note]
There is an implementation-defined quantity that specifies the limit on the total depth of recursive instantiations ([implimits]), which could involve more than one template.
The result of an infinite recursion in instantiation is undefined.
[Example 9: template<class T> class X { X<T>* p; // OK X<T*> a; // implicit generation of X<T> requires // the implicit instantiation of X<T*> which requires // the implicit instantiation of X<T**> which … }; — end example]
The type-constraints and requires-clause of a template specialization or member function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in [temp.constr.decl] and [temp.constr.atomic] when determining whether the constraints are satisfied or as specified in [temp.constr.decl] when comparing declarations.
[Note 7: 
The satisfaction of constraints is determined during template argument deduction ([temp.deduct]) and overload resolution ([over.match]).
— end note]
[Example 10: template<typename T> concept C = sizeof(T) > 2; template<typename T> concept D = C<T> && sizeof(T) > 4; template<typename T> struct S { S() requires C<T> { } // #1 S() requires D<T> { } // #2 }; S<char> s1; // error: no matching constructor S<char[8]> s2; // OK, calls #2
When S<char> is instantiated, both constructors are part of the specialization.
Their constraints are not satisfied, and they suppress the implicit declaration of a default constructor for S<char> ([class.default.ctor]), so there is no viable constructor for s1.
— end example]
[Example 11: template<typename T> struct S1 { template<typename U> requires false struct Inner1; // ill-formed, no diagnostic required }; template<typename T> struct S2 { template<typename U> requires (sizeof(T[-(int)sizeof(T)]) > 1) struct Inner2; // ill-formed, no diagnostic required };
The class S1<T>​::​Inner1 is ill-formed, no diagnostic required, because it has no valid specializations.
S2 is ill-formed, no diagnostic required, since no substitution into the constraints of its Inner2 template would result in a valid expression.
— end example]

13.9.3 Explicit instantiation [temp.explicit]

A class, function, variable, or member template specialization can be explicitly instantiated from its template.
A member function, member class or static data member of a class template can be explicitly instantiated from the member definition associated with its class template.
The syntax for explicit instantiation is:
There are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration.
An explicit instantiation declaration begins with the extern keyword.
An explicit instantiation shall not use a storage-class-specifier ([dcl.stc]) other than thread_local.
An explicit instantiation of a function template, member function of a class template, or variable template shall not use the inline, constexpr, or consteval specifiers.
No attribute-specifier-seq ([dcl.attr.grammar]) shall appertain to an explicit instantiation.
If the explicit instantiation is for a class or member class, the elaborated-type-specifier in the declaration shall include a simple-template-id; otherwise, the declaration shall be a simple-declaration whose init-declarator-list comprises a single init-declarator that does not have an initializer.
If the explicit instantiation is for a variable template specialization, the unqualified-id in the declarator shall be a simple-template-id.
[Example 1: template<class T> class Array { void mf(); }; template class Array<char>; template void Array<int>::mf(); template<class T> void sort(Array<T>& v) { /* ... */ } template void sort(Array<char>&); // argument is deduced here namespace N { template<class T> void f(T&) { } } template void N::f<int>(int&); — end example]
An explicit instantiation does not introduce a name ([basic.scope.scope]).
A declaration of a function template, a variable template, a member function or static data member of a class template, or a member function template of a class or class template shall be reachable from any explicit instantiation of that entity.
A definition of a class template, a member class of a class template, or a member class template of a class or class template shall be reachable from any explicit instantiation of that entity unless an explicit specialization of the entity with the same template arguments is reachable therefrom.
If the declaration of the explicit instantiation names an implicitly-declared special member function ([special]), the program is ill-formed.
The declaration in an explicit-instantiation and the declaration produced by the corresponding substitution into the templated function, variable, or class are two declarations of the same entity.
[Note 1: 
These declarations need to have matching types as specified in [basic.link], except as specified in [except.spec].
[Example 2: template<typename T> T var = {}; template float var<float>; // OK, instantiated variable has type float template int var<int[16]>[]; // OK, absence of major array bound is permitted template int *var<int>; // error: instantiated variable has type int template<typename T> auto av = T(); template int av<int>; // OK, variable with type int can be redeclared with type auto template<typename T> auto f() {} template void f<int>(); // error: function with deduced return type // redeclared with non-deduced return type ([dcl.spec.auto]) — end example]
— end note]
Despite its syntactic form, the declaration in an explicit-instantiation for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable.
For a given set of template arguments, if an explicit instantiation of a template appears after a declaration of an explicit specialization for that template, the explicit instantiation has no effect.
Otherwise, for an explicit instantiation definition, the definition of a function template, a variable template, a member function template, or a member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
A trailing template-argument can be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced ([temp.deduct.decl]).
If all template arguments can be deduced, the empty template argument list <> may be omitted.
[Example 3: template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } // instantiate sort(Array<int>&) -- template-argument deduced template void sort<>(Array<int>&); — end example]
[Note 2: 
An explicit instantiation of a constrained template needs to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit instantiation in which all template arguments are specified ([temp.names]), or, for explicit instantiations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— end note]
An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each of its direct non-template members that has not been previously explicitly specialized in the translation unit containing the explicit instantiation, provided that the associated constraints, if any, of that member are satisfied by the template arguments of the explicit instantiation ([temp.constr.decl], [temp.constr.constr]), except as described below.
[Note 3: 
In addition, it will typically be an explicit instantiation of certain implementation-dependent data about the class.
— end note]
An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.
An explicit instantiation of a prospective destructor ([class.dtor]) shall correspond to the selected destructor of the class.
If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration.
An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required.
[Note 4: 
This rule does apply to inline functions even though an explicit instantiation declaration of such an entity has no other normative effect.
This is needed to ensure that if the address of an inline function is taken in a translation unit in which the implementation chose to suppress the out-of-line body, another translation unit will supply the body.
— end note]
An explicit instantiation declaration shall not name a specialization of a template with internal linkage.
An explicit instantiation does not constitute a use of a default argument, so default argument instantiation is not done.
[Example 4: char* p = 0; template<class T> T g(T x = &p) { return x; } template int g<int>(int); // OK even though &p isn't an int. — end example]

13.9.4 Explicit specialization [temp.expl.spec]

An explicit specialization of any of the following:
  • function template
  • class template
  • variable template
  • member function of a class template
  • static data member of a class template
  • member class of a class template
  • member enumeration of a class template
  • member class template of a class or class template
  • member function template of a class or class template
can be declared by a declaration introduced by template<>; that is:
[Example 1: template<class T> class stream; template<> class stream<char> { /* ... */ }; template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v) { /* ... */ } template<> void sort<char*>(Array<char*>&);
Given these declarations, stream<char> will be used as the definition of streams of chars; other streams will be handled by class template specializations instantiated from the class template.
Similarly, sort<char*> will be used as the sort function for arguments of type Array<char*>; other Array types will be sorted by functions generated from the template.
— end example]
An explicit specialization shall not use a storage-class-specifier ([dcl.stc]) other than thread_local.
An explicit specialization may be declared in any scope in which the corresponding primary template may be defined ([dcl.meaning], [class.mem], [temp.mem]).
An explicit specialization does not introduce a name ([basic.scope.scope]).
A declaration of a function template, class template, or variable template being explicitly specialized shall be reachable from the declaration of the explicit specialization.
[Note 1: 
A declaration, but not a definition of the template is needed.
— 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.
[Example 2: template<> class X<int> { /* ... */ }; // error: X not a template template<class T> class X; template<> class X<char*> { /* ... */ }; // OK, X is a template — end example]
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.
If such an explicit specialization for the member of a class template names an implicitly-declared special member function ([special]), the program is ill-formed.
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.
The definition of the class template explicit specialization shall be reachable from the definition of any member of it.
The definition of an explicitly specialized class is unrelated to the definition of a generated specialization.
That is, its members need not have the same names, types, etc. as the members of a generated specialization.
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
The same is true when defining a member of an explicitly specialized member class.
However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.
[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 template void A<int>::f(int) { /* ... */ } template<> struct A<char>::B { void f(); }; // template<> also not used when defining a member of an explicitly specialized member class void 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 template template<> 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 permitted template<> template<class U> struct A<short>::C { void f(); }; template<class U> void A<short>::C<U>::f() { /* ... */ } // error: template<> required — end example]
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.
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.
An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
[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 template template<> void sort<>(Array<char*>& v); // OK, sort<char*> not yet used template<class T> struct A { enum E : T; enum class S : T; }; template<> enum A<int>::E : int { eint }; // OK template<> enum class A<int>::S : int { sint }; // OK template<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 instantiated template<> enum class A<char>::S : char { schar }; // OK — end example]
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.
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.
A simple-template-id that names a class template explicit specialization that has been declared but not defined can be used exactly like the names of other incompletely-defined classes ([basic.types]).
[Example 5: template<class T> class X; // X is a class template template<> 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]
A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced ([temp.deduct.decl]).
[Example 6: template<class T> class Array { /* ... */ }; template<class T> void sort(Array<T>& v); // explicit specialization for sort(Array<int>&) // with deduced template-argument of type int template<> void sort(Array<int>&); — end example]
[Note 2: 
An explicit specialization of a constrained template needs to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit specialization in which all template arguments are specified ([temp.names]), or, for explicit specializations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— end note]
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]).
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.
Similarly, attributes appearing in the declaration of a template have no effect on an explicit specialization of that template.
[Example 7: template<class T> void f(T) { /* ... */ } template<class T> inline T g(T) { /* ... */ } template<> inline void f<>(int) { /* ... */ } // OK, inline template<> int g<>(int) { /* ... */ } // OK, not inline template<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]
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.
[Note 3: 
The definition of a static data member of a template for which default-initialization is desired can use functional cast notation ([expr.type.conv]): template<> X Q<int>::x; // declaration template<> X Q<int>::x (); // error: declares a function template<> X Q<int>::x = X(); // definition
— end note]
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.
An explicit specialization of a member or member template is specified using the syntax for explicit specialization.
[Example 8: 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) { } }; // specialization template<> void A<int>::f(int); // out of class member template definition template<class T> template<class X1> void A<T>::g1(T, X1) { } // member template specialization template<> template<class X1> void A<int>::g1(int, X1); // member template specialization template<> template<> void A<int>::g1(int, char); // X1 deduced as char template<> template<> void A<int>::g2<char>(int, char); // X2 specified as char // member specialization even if defined in class definition template<> void A<int>::h(int) { } — end example]
A member or a member template may be nested within many enclosing class templates.
In an explicit specialization for such a member, the member declaration shall be preceded by a template<> for each enclosing class template that is explicitly specialized.
[Example 9: 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]
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.
In such an explicit specialization declaration, the keyword template followed by a template-parameter-list shall be provided instead of the template<> preceding the explicit specialization declaration of the member.
The types of the template-parameters in the template-parameter-list shall be the same as those specified in the primary template definition.
[Example 10: 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]
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.
An explicit specialization declaration shall not be a friend declaration.
Default function arguments shall not be specified in a declaration or a definition for one of the following explicit specializations:
  • the explicit specialization of a function template;
  • the explicit specialization of a member function template;
  • 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.
    [Note 4: 
    Default function arguments can be specified in the declaration or definition of a member function of a class template specialization that is explicitly specialized.
    — end note]