[temp.spec] (original) (raw)
13 Templates [temp]
13.9 Template instantiation and specialization [temp.spec]
The act of instantiating a function, a variable, a class, a member of a class template, or a member template is referred to astemplate 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 bytemplate<>.
In an explicit specialization declaration for a variable template, a class template, a member of a class template or a class member template, the name of the variable or class that is explicitly specialized shall be asimple-template-id.
In the explicit specialization declaration for a function template or a member function template, the name of the function or member function explicitly specialized may be atemplate-id.
[ Example
:
template struct A { static int x; }; template void g(U) { }
template<> struct A { };
template<> struct A<> { };
template<> void g(char) { }
template<> void g(int) { }
template<> int A::x = 0;
template struct B { static int x; }; template<> int B<>::x = 1;
— 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 oftemplate-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 instantiation follows a declaration of the explicit specialization.
An implementation is not required to diagnose a violation of this rule.
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
:
In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may 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
:
template class X { static T s; }; template T X::s = 0; X aa; X<char*> bb;
X<int>has a static membersof typeintandX<char*>has a static membersof typechar*.
— 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
:
template struct A { static T t; }; typedef int function(); A a;
— end example
]
13.9.1 Implicit instantiation [temp.inst]
A template specialization E is a declared specializationif 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 andE is not
- an inline function,
- declared with a type deduced from its initializer or return value ([dcl.spec.auto]),
- a potentially-constant variable ([expr.const]), or
- a specialization of a templated class.
[ Note
:
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
:
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
:
template class B { }; template class D : public B { };
void f(void*); void f(B*);
void g(D* p, D* pp, D* ppp) {
f(p);
B* q = pp;
delete ppp;
}
— end example
]
If a class template has been declared, but not defined, at the point of instantiation, the instantiation yields an incomplete class type ([basic.types]).
[ Example
:
template class X; X ch;
— end example
]
[ Note
:
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-specifiersof the class member functions.
[ Example
:
template
struct C {
void f() { T x; }
void g() = delete;
};
C c;
template<> void C::g() { }
— end example
]
However, for the purpose of determining whether an instantiated redeclaration is valid according to [basic.def.odr] and [class.mem], a declaration that corresponds to a definition in the template is considered to be a definition.
[ Example
:
template<class T, class U>
struct Outer {
template<class X, class Y> struct Inner;
template struct Inner<T, Y>;
template struct Inner<T, Y> { };
template struct Inner<U, Y> { };
};
Outer<int, int> outer;
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 struct Friendly { template friend int f(U) { return sizeof(T); } }; Friendly fc; Friendly ff;
— end example
]
Unless a member of a class template or a member template 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
:
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
:
template struct Z { void f(); void g(); };
void h() {
Z a;
Z* p;
Z* q;
a.f();
p->g();
}
Nothing in this example requiresclass Z<double>,Z<int>::g(), orZ<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
:
template constexpr int f() { return T::value; } template<bool B, typename T> void g(decltype(B ? f() : 0)); template<bool B, typename T> void g(...); template<bool B, typename T> void h(decltype(int{B ? f() : 0})); template<bool B, typename T> void h(...); void x() { g<false, int>(0); h<false, int>(0);
}
— end example
]
If the function selected by overload resolutioncan be determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
[ Example
:
template struct S { operator int(); };
void f(int); void f(S&); void f(S);
void g(S& sr) { f(sr);
};
— 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, a static data member of a class template, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
[ Note
:
The instantiation of a generic lambda does not require instantiation of substatements of a constexpr if statement within its compound-statementunless 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 shall not cause the template to be implicitly instantiated except that a class template may be instantiated where its complete type is needed to determine the correctness of the default argument.
The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
Implicitly instantiated class, function, and variable template specializations are placed in the namespace where the template is defined.
Implicitly instantiated specializations for members of a class template are placed in the namespace where the enclosing class template is defined.
Implicitly instantiated member templates are placed in the namespace where the enclosing class or class template is defined.
[ Example
:
namespace N { template class List { public: T* get(); }; }
template<class K, class V> class Map { public: N::List lt; V get(K); };
void g(Map<const char*,int>& m) { int i = m.get("Nicholas"); }
A call oflt.get()fromMap<const char*,int>::get()would placeList<int>::get()in the namespaceNrather than in the global namespace.
— end example
]
If a function templatefis 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 templatefused 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 calleddefault argument instantiation.
The instantiated default argument is then used as the argument off.
Each default argument is instantiated independently.
[ Example
:
template 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);
f(a, b);
f(a);
}
— 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 annoexcept-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 thenoexcept-specifier is done as if it were being done as part of instantiating the declaration of the specialization at that point.
[ Note
:
[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
:
template class X {
X* p;
X<T*> a;
};
— end example
]
The type-constraints and requires-clauseof 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
:
The satisfaction of constraints is determined during template argument deduction ([temp.deduct]) and overload resolution ([over.match]).
— end note
]
[ Example
:
template concept C = sizeof(T) > 2; template concept D = C && sizeof(T) > 4;
template struct S {
S() requires C { }
S() requires D { }
};
S s1;
S<char[8]> s2;
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 forS<char> ([class.default.ctor]), so there is no viable constructor for s1.
— end example
]
[ Example
:
template struct S1 {
template
requires false
struct Inner1;
};
template struct S2 {
template
requires (sizeof(T[-(int)sizeof(T)]) > 1)
struct Inner2;
};
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.2 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:
explicit-instantiation: extern template declaration
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 of a function template, member function of a class template, or variable template shall not use the inline, constexpr, or consteval specifiers.
If the explicit instantiation is for a member function, a member class or a static data member of a class template specialization, the name of the class template specialization in thequalified-idfor the member name shall be a simple-template-id.
An explicit instantiation shall appear in an enclosing namespace of its template.
If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared or, if that namespace is inline ([namespace.def]), any namespace from its enclosing namespace set.
[ Note
:
Regarding qualified names in declarators, see [dcl.meaning].
— end note
]
[ Example
:
template class Array { void mf(); }; template class Array; template void Array::mf();
template void sort(Array& v) { } template void sort(Array&);
namespace N { template void f(T&) { } } template void N::f(int&);
— end example
]
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 precede an 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 precede an explicit instantiation of that entity unless the explicit instantiation is preceded by an explicit specialization of the entity with the same template arguments.
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
:
These declarations are required to have matching types as specified in [basic.link], except as specified in [except.spec].
[ Example
:
template T var = {};
template float var;
template int var<int[16]>[];
template int *var;
template auto av = T(); template int av;
template auto f() {} template void f();
— 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.
An explicit instantiation of a class, function template, or variable template specialization is placed in the namespace in which the template is defined.
An explicit instantiation for a member of a class template is placed in the namespace where the enclosing class template is defined.
An explicit instantiation for a member template is placed in the namespace where the enclosing class or class template is defined.
[ Example
:
namespace N { template class Y { void mf() { } }; }
template class Y;
using N::Y; template class Y;
template class N::Y<char*>;
template void N::Y::mf();
— end example
]
A trailingtemplate-argumentcan be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced from the type of a function parameter ([temp.deduct]).
[ Example
:
template class Array { }; template void sort(Array& v) { }
template void sort<>(Array&);
— end example
]
[ Note
:
An explicit instantiation of a constrained template is required 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 members (not including members inherited from base classes and members that are templates) 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
:
In addition, it will typically be an explicit instantiation of certainimplementation-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 name 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 instantiationin 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
:
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
:
char* p = 0; template T g(T x = &p) { return x; } template int g(int);
— end example
]
13.9.3 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 bytemplate<>; that is:
explicit-specialization: template < > declaration
[ Example
:
template class stream;
template<> class stream { };
template class Array { }; template void sort(Array& v) { }
template<> void sort<char*>(Array<char*>&);
Given these declarations,stream<char>will be used as the definition of streams ofchars; 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 typeArray<char*>; otherArraytypes will be sorted by functions generated from the template.
— end example
]
A declaration of a function template, class template, or variable template being explicitly specialized shall precede the declaration of the explicit specialization.
[ Note
:
A declaration, but not a definition of the template is required.
— end note
]
The definition of a class or class template shall precede the declaration of an explicit specialization for a member template of the class or class template.
[ Example
:
template<> class X { };
template class X;
template<> class X<char*> { };
— 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 precede 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.
In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined.
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
:
template struct A { struct B { }; template struct C { }; };
template<> struct A { void f(int); };
void h() {
A a;
a.f(16);
}
void A::f(int) { }
template<> struct A::B { void f(); };
void A::B::f() { }
template<> template struct A::C { void f(); };
template<> template void A::C::f() { }
template<> struct A::B { void f(); }; template<> void A::B::f() { }
template<> template struct A::C { void f(); }; template void A::C::f() { }
— end example
]
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first 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
:
class String { }; template class Array { }; template void sort(Array& v) { }
void f(Array& v) {
sort(v);
}
template<> void sort(Array& v);
template<> void sort<>(Array<char*>& v);
template struct A {
enum E : T;
enum class S : T;
};
template<> enum A::E : int { eint };
template<> enum class A::S : int { sint };
template enum A::E : T { eT };
template enum class A::S : T { sT };
template<> enum A::E : char { echar };
template<> enum class A::S : char { schar };
— 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 template explicit specialization is in the scope of the namespace in which the template was defined.
[ Example
:
namespace N { template class X { }; template class Y { };
template<> class X { };
template<> class Y;
}
template<> class N::Y { };
template<> class N::Y { };
— end example
]
Asimple-template-idthat 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
:
template class X;
template<> class X;
X* p;
X x;
— end example
]
A trailingtemplate-argumentcan be left unspecified in thetemplate-idnaming an explicit function template specialization provided it can be deduced from the function argument type.
[ Example
:
template class Array { }; template void sort(Array& v);
template<> void sort(Array&);
— end example
]
[ Note
:
An explicit specialization of a constrained template is required 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, or an immediate function is determined by the explicit specialization and is independent of those properties of the template.
[ Example
:
template void f(T) { } template inline T g(T) { }
template<> inline void f<>(int) { }
template<> int g<>(int) { }
— 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
:
The definition of a static data member of a template that requires default-initialization must use a braced-init-list:
template<> X Q::x;
template<> X Q::x ();
template<> X Q::x { };
— 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
:
template struct A { void f(T); template void g1(T, X1); template void g2(T, X2); void h(T) { } };
template<> void A::f(int);
template template void A::g1(T, X1) { }
template<> template void A::g1(int, X1);
template<> template<>
void A::g1(int, char);
template<> template<>
void A::g2(int, char);
template<> void A::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 atemplate<>for each enclosing class template that is explicitly specialized.
[ Example
:
template class A { template class B { void mf(); }; }; template<> template<> class A::B; template<> template<> void A::B::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 keywordtemplatefollowed by atemplate-parameter-listshall be provided instead of thetemplate<>preceding the explicit specialization declaration of the member.
[ Example
:
template class A { template class B { template void mf1(T3); void mf2(); }; }; template <> template class A::B { template void mf1(T); }; template <> template <> template void A::B::mf1(T t) { } template template <> void A::B::mf2() { }
— 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
: Default function arguments may be specified in the declaration or definition of a member function of a class template specialization that is explicitly specialized. — end note
]