1137 lines
59 KiB
Markdown
1137 lines
59 KiB
Markdown
[temp.spec]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.9 Template instantiation and specialization [temp.spec]
|
||
|
||
### [13.9.1](#general) General [[temp.spec.general]](temp.spec.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6345)
|
||
|
||
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*](#def:template_instantiation "13.9.1 General [temp.spec.general]")[.](#general-1.sentence-1)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6352)
|
||
|
||
A function instantiated from a function template is called an instantiated
|
||
function[.](#general-2.sentence-1)
|
||
|
||
A class instantiated from a class template is called an instantiated class[.](#general-2.sentence-2)
|
||
|
||
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[.](#general-2.sentence-3)
|
||
|
||
A member function instantiated from a member function template is called an
|
||
instantiated member function[.](#general-2.sentence-4)
|
||
|
||
A member class instantiated from a member class template is called an
|
||
instantiated member class[.](#general-2.sentence-5)
|
||
|
||
A variable instantiated from a variable template is called an
|
||
instantiated variable[.](#general-2.sentence-6)
|
||
|
||
A static data member instantiated from a static data member template
|
||
is called an instantiated static data member[.](#general-2.sentence-7)
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6369)
|
||
|
||
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[.](#general-3.sentence-1)
|
||
|
||
An explicit specialization declaration is introduced bytemplate<>[.](#general-3.sentence-2)
|
||
|
||
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*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#general-3.sentence-3)
|
||
|
||
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*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")[.](#general-3.sentence-4)
|
||
|
||
[*Example [1](#general-example-1)*: template<class T = int> struct A {static int x;};template<class U> void g(U) { }template<> struct A<double> { }; // specialize for T == doubletemplate<> struct A<> { }; // specialize for T == inttemplate<> void g(char) { } // specialize for U == char// U is deduced from the parameter typetemplate<> void g<int>(int) { } // specialize for U == inttemplate<> int A<char>::x = 0; // specialize for T == chartemplate<class T = int> struct B {static int x;};template<> int B<>::x = 1; // specialize for T == int â *end example*]
|
||
|
||
[4](#general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6405)
|
||
|
||
An instantiated template specialization can be either implicitly
|
||
instantiated ([[temp.inst]](#temp.inst "13.9.2 Implicit instantiation")) for a given argument list or be explicitly
|
||
instantiated ([[temp.explicit]](#temp.explicit "13.9.3 Explicit instantiation"))[.](#general-4.sentence-1)
|
||
|
||
A [*specialization*](#def:specialization "13.9.1 General [temp.spec.general]") is a class, variable, function, or class member that is either
|
||
instantiated ([[temp.inst]](#temp.inst "13.9.2 Implicit instantiation")) from a templated entity or is an
|
||
explicit specialization ([[temp.expl.spec]](#temp.expl.spec "13.9.4 Explicit specialization")) of a templated entity[.](#general-4.sentence-2)
|
||
|
||
[5](#general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6413)
|
||
|
||
For a given template and a given set of[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*,
|
||
|
||
- [(5.1)](#general-5.1)
|
||
|
||
an explicit instantiation definition shall appear at most once in a program,
|
||
|
||
- [(5.2)](#general-5.2)
|
||
|
||
an explicit specialization shall be defined at most once
|
||
in a program, as specified in [[basic.def.odr]](basic.def.odr "6.3 One-definition rule"), and
|
||
|
||
- [(5.3)](#general-5.3)
|
||
|
||
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[.](#general-5.sentence-1)
|
||
|
||
An implementation is not required to diagnose a violation of this rule
|
||
if neither declaration is reachable from the other[.](#general-5.sentence-2)
|
||
|
||
[6](#general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6430)
|
||
|
||
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*](class.derived.general#nt:base-clause "11.7.1 General [class.derived.general]"), [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]"), [*enumerator-list*](dcl.enum#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]"),
|
||
or static data member or variable template initializer[.](#general-6.sentence-1)
|
||
|
||
[*Note [1](#general-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[.](#general-6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[7](#general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6443)
|
||
|
||
Each class template specialization instantiated from a template has its own
|
||
copy of any static members[.](#general-7.sentence-1)
|
||
|
||
[*Example [2](#general-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 members of typeint andX<char*> has a static members of typechar*[.](#general-7.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[8](#general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6469)
|
||
|
||
If a function declaration acquired its function type through
|
||
a [dependent type](temp.dep.type "13.8.3.2 Dependent types [temp.dep.type]") without using the syntactic form of
|
||
a function declarator, the program is ill-formed[.](#general-8.sentence-1)
|
||
|
||
[*Example [3](#general-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](#temp.inst) Implicit instantiation [[temp.inst]](temp.inst)
|
||
|
||
[1](#temp.inst-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6485)
|
||
|
||
A template specialization E is a [*declared specialization*](#def:specialization,declared "13.9.2 Implicit instantiation [temp.inst]") if there is a reachable
|
||
explicit instantiation definition ([[temp.explicit]](#temp.explicit "13.9.3 Explicit instantiation")) or
|
||
explicit specialization declaration ([[temp.expl.spec]](#temp.expl.spec "13.9.4 Explicit specialization"))
|
||
for E, or
|
||
if there is a reachable explicit instantiation declaration for E andE is not
|
||
|
||
- [(1.1)](#temp.inst-1.1)
|
||
|
||
an inline function,
|
||
|
||
- [(1.2)](#temp.inst-1.2)
|
||
|
||
declared with a type deduced
|
||
from its initializer or return value ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")),
|
||
|
||
- [(1.3)](#temp.inst-1.3)
|
||
|
||
a potentially-constant variable ([[expr.const]](expr.const "7.7 Constant expressions")), or
|
||
|
||
- [(1.4)](#temp.inst-1.4)
|
||
|
||
a specialization of a templated class[.](#temp.inst-1.sentence-1)
|
||
|
||
[*Note [1](#temp.inst-note-1)*:
|
||
|
||
An implicit instantiation in an importing translation unit
|
||
cannot use names with internal linkage
|
||
from an imported translation unit ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#temp.inst-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#temp.inst-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6510)
|
||
|
||
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[.](#temp.inst-2.sentence-1)
|
||
|
||
[*Note [2](#temp.inst-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[.](#temp.inst-2.sentence-2)
|
||
|
||
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[.](#temp.inst-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#temp.inst-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]](temp.spec.partial.match "13.7.6.2 Matching of partial specializations"))
|
||
has been declared, but not defined,
|
||
at the point of instantiation ([[temp.point]](temp.point "13.8.4.1 Point of instantiation")),
|
||
the instantiation yields an incomplete class type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1 General"))[.](#temp.inst-2.sentence-4)
|
||
|
||
[*Example [2](#temp.inst-example-2)*: template<class T> class X;
|
||
X<char> ch; // error: incomplete type X<char> â *end example*]
|
||
|
||
[*Note [3](#temp.inst-note-3)*:
|
||
|
||
Within a template declaration,
|
||
a [local class](class.local "11.6 Local class declarations [class.local]") 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-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s*, and non-static data member
|
||
initializers, if any,
|
||
but not their [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* or [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*)[.](#temp.inst-2.sentence-5)
|
||
|
||
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[.](#temp.inst-2.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[3](#temp.inst-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6564)
|
||
|
||
The implicit instantiation of a class template specialization causes
|
||
|
||
- [(3.1)](#temp.inst-3.1)
|
||
|
||
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
|
||
|
||
- [(3.2)](#temp.inst-3.2)
|
||
|
||
the implicit instantiation of the definitions of
|
||
deleted member functions,
|
||
unscoped member enumerations, and
|
||
member anonymous unions[.](#temp.inst-3.sentence-1)
|
||
|
||
The implicit instantiation of a class template specialization
|
||
does not cause the implicit instantiation of
|
||
default arguments or [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of the class member functions[.](#temp.inst-3.sentence-2)
|
||
|
||
[*Example [3](#temp.inst-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 pointtemplate<> 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]](basic.def.odr "6.3 One-definition rule") and [[class.mem]](class.mem "11.4 Class members"),
|
||
an instantiated declaration that corresponds to a definition in the template
|
||
is considered to be a definition[.](#temp.inst-3.sentence-3)
|
||
|
||
[*Example [4](#temp.inst-example-4)*: template<class T, class U>struct Outer {template<class X, class Y> struct Inner; template<class Y> struct Inner<T, Y>; // #1atemplate<class Y> struct Inner<T, Y> { }; // #1b; OK, valid redeclaration of #1atemplate<class Y> struct Inner<U, Y> { }; // #2};
|
||
|
||
Outer<int, int> outer; // error at #2
|
||
|
||
Outer<int, int>::Inner<int, Y> is redeclared at #1b[.](#temp.inst-3.sentence-4)
|
||
|
||
(It is not defined
|
||
but noted as being associated with a definition in Outer<T, U>[.](#temp.inst-3.sentence-5))
|
||
|
||
#2
|
||
is also a redeclaration of #1a[.](#temp.inst-3.sentence-6)
|
||
|
||
It is noted as associated with a definition,
|
||
so it is an invalid redeclaration of the same partial specialization[.](#temp.inst-3.sentence-7)
|
||
|
||
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*]
|
||
|
||
[4](#temp.inst-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6628)
|
||
|
||
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[.](#temp.inst-4.sentence-1)
|
||
|
||
[5](#temp.inst-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6639)
|
||
|
||
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[.](#temp.inst-5.sentence-1)
|
||
|
||
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[.](#temp.inst-5.sentence-2)
|
||
|
||
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[.](#temp.inst-5.sentence-3)
|
||
|
||
[*Note [4](#temp.inst-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]](basic.def.odr#term.odr.use "6.3 One-definition rule"))
|
||
so that the body can be considered for inlining,
|
||
but that no out-of-line copy of it be generated in the translation unit[.](#temp.inst-5.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[6](#temp.inst-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6664)
|
||
|
||
[*Example [5](#temp.inst-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 requiresclassZ<double>,Z<int>::g(),
|
||
orZ<char>::f() to be implicitly instantiated[.](#temp.inst-6.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
[7](#temp.inst-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6692)
|
||
|
||
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[.](#temp.inst-7.sentence-1)
|
||
|
||
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[.](#temp.inst-7.sentence-2)
|
||
|
||
[8](#temp.inst-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6702)
|
||
|
||
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]](expr.const "7.7 Constant expressions")),
|
||
even if constant evaluation of the expression is not required or
|
||
if constant expression evaluation does not use the definition[.](#temp.inst-8.sentence-1)
|
||
|
||
[*Example [6](#temp.inst-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*]
|
||
|
||
[9](#temp.inst-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6729)
|
||
|
||
If the function selected by [overload resolution](over.match "12.2 Overload resolution [over.match]") can be determined without instantiating a class template definition,
|
||
it is unspecified whether that instantiation actually takes place[.](#temp.inst-9.sentence-1)
|
||
|
||
[*Example [7](#temp.inst-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*]
|
||
|
||
[10](#temp.inst-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6750)
|
||
|
||
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]](temp.over "13.10.4 Overload resolution"))[.](#temp.inst-10.sentence-1)
|
||
|
||
[11](#temp.inst-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6755)
|
||
|
||
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]](stmt.if "8.5.2 The if statement")), unless such instantiation is required[.](#temp.inst-11.sentence-1)
|
||
|
||
[*Note [5](#temp.inst-note-5)*:
|
||
|
||
The instantiation of a generic lambda
|
||
does not require instantiation of
|
||
substatements of a constexpr if statement
|
||
within its [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") unless the call operator template is instantiated[.](#temp.inst-11.sentence-2)
|
||
|
||
â *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[.](#temp.inst-11.sentence-3)
|
||
|
||
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[.](#temp.inst-11.sentence-4)
|
||
|
||
The use of a default argument in a
|
||
function call causes specializations in the default argument to be implicitly
|
||
instantiated[.](#temp.inst-11.sentence-5)
|
||
|
||
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[.](#temp.inst-11.sentence-6)
|
||
|
||
[12](#temp.inst-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6783)
|
||
|
||
If a templated functionf 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 templatef used at that point, except that the scope in which a closure type is
|
||
declared ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")) â and therefore its associated namespaces â
|
||
remain as determined from the context of the definition for the default
|
||
argument[.](#temp.inst-12.sentence-1)
|
||
|
||
This analysis is called[*default argument instantiation*](#def:default_argument_instantiation "13.9.2 Implicit instantiation [temp.inst]")[.](#temp.inst-12.sentence-2)
|
||
|
||
The instantiated default argument is then used as the argument off[.](#temp.inst-12.sentence-3)
|
||
|
||
[13](#temp.inst-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6802)
|
||
|
||
Each default argument is instantiated independently[.](#temp.inst-13.sentence-1)
|
||
|
||
[*Example [8](#temp.inst-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*]
|
||
|
||
[14](#temp.inst-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6820)
|
||
|
||
The [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") and [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")*s* of a function template specialization
|
||
are not instantiated along with the function declaration;
|
||
they are instantiated
|
||
when needed ([[except.spec]](except.spec "14.5 Exception specifications"), [[dcl.contract.func]](dcl.contract.func "9.4.1 General"))[.](#temp.inst-14.sentence-1)
|
||
|
||
If such a
|
||
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
|
||
specifier is done as if it were being done as part
|
||
of instantiating the declaration of the specialization at that point[.](#temp.inst-14.sentence-2)
|
||
|
||
[15](#temp.inst-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6832)
|
||
|
||
[*Note [6](#temp.inst-note-6)*:
|
||
|
||
[[temp.point]](temp.point "13.8.4.1 Point of instantiation") defines the point of instantiation of a template specialization[.](#temp.inst-15.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[16](#temp.inst-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6837)
|
||
|
||
There is an implementation-defined quantity
|
||
that specifies the limit on the total depth of recursive instantiations ([[implimits]](implimits "Annex B (informative) Implementation quantities")),
|
||
which could involve more than one template[.](#temp.inst-16.sentence-1)
|
||
|
||
The result of an infinite recursion in instantiation is undefined[.](#temp.inst-16.sentence-2)
|
||
|
||
[*Example [9](#temp.inst-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*]
|
||
|
||
[17](#temp.inst-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6853)
|
||
|
||
The [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") 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]](temp.constr.decl "13.5.3 Constrained declarations") and [[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints") when determining whether the constraints are satisfied
|
||
or as specified in [[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations") when comparing declarations[.](#temp.inst-17.sentence-1)
|
||
|
||
[*Note [7](#temp.inst-note-7)*:
|
||
|
||
The satisfaction of constraints is determined during
|
||
template argument deduction ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")) and
|
||
overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#temp.inst-17.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [10](#temp.inst-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[.](#temp.inst-17.sentence-3)
|
||
|
||
Their constraints are not satisfied, and
|
||
they suppress the implicit declaration of a default constructor forS<char> ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors")), so there is no viable constructor
|
||
for s1[.](#temp.inst-17.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[*Example [11](#temp.inst-example-11)*: template<typename T> struct S1 {template<typename U>requires falsestruct 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[.](#temp.inst-17.sentence-5)
|
||
|
||
S2 is ill-formed, no diagnostic required, since no substitution into
|
||
the constraints of its Inner2 template would result in a valid
|
||
expression[.](#temp.inst-17.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
### [13.9.3](#temp.explicit) Explicit instantiation [[temp.explicit]](temp.explicit)
|
||
|
||
[1](#temp.explicit-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6909)
|
||
|
||
A class, function, variable, or member template specialization can be explicitly
|
||
instantiated from its template[.](#temp.explicit-1.sentence-1)
|
||
|
||
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[.](#temp.explicit-1.sentence-2)
|
||
|
||
[2](#temp.explicit-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6918)
|
||
|
||
The syntax for explicit instantiation is:
|
||
|
||
[explicit-instantiation:](#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]")
|
||
externopt template [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")
|
||
|
||
There are two forms of explicit instantiation: an explicit instantiation
|
||
definition and an explicit instantiation declaration[.](#temp.explicit-2.sentence-2)
|
||
|
||
An explicit instantiation
|
||
declaration begins with the extern keyword[.](#temp.explicit-2.sentence-3)
|
||
|
||
[3](#temp.explicit-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6929)
|
||
|
||
An explicit instantiation 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[.](#temp.explicit-3.sentence-1)
|
||
|
||
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[.](#temp.explicit-3.sentence-2)
|
||
|
||
No [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"))
|
||
shall appertain to an explicit instantiation[.](#temp.explicit-3.sentence-3)
|
||
|
||
[4](#temp.explicit-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6942)
|
||
|
||
If the explicit instantiation is for a class or member class, the[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") in the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") shall include a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]");
|
||
otherwise, the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") shall be a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") whose [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") comprises a single [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") that does not have an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#temp.explicit-4.sentence-1)
|
||
|
||
If the explicit instantiation is for a variable template specialization,
|
||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") in the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#temp.explicit-4.sentence-2)
|
||
|
||
[*Example [1](#temp.explicit-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 ([[temp.arg.explicit]](temp.arg.explicit "13.10.2 Explicit template argument specification"))namespace N {template<class T> void f(T&) { }}template void N::f<int>(int&); â *end example*]
|
||
|
||
[5](#temp.explicit-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6969)
|
||
|
||
An explicit instantiation does not introduce a name ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))[.](#temp.explicit-5.sentence-1)
|
||
|
||
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[.](#temp.explicit-5.sentence-2)
|
||
|
||
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[.](#temp.explicit-5.sentence-3)
|
||
|
||
If the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") of the explicit instantiation names an implicitly-declared special member
|
||
function ([[special]](special "11.4.4 Special member functions")), the program is ill-formed[.](#temp.explicit-5.sentence-4)
|
||
|
||
[6](#temp.explicit-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6985)
|
||
|
||
The [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") and
|
||
the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") produced by the corresponding substitution
|
||
into the templated function, variable, or class
|
||
are two declarations of the same entity[.](#temp.explicit-6.sentence-1)
|
||
|
||
[*Note [1](#temp.explicit-note-1)*:
|
||
|
||
These declarations need to have matching types as specified in [[basic.link]](basic.link "6.7 Program and linkage"), except as specified in [[except.spec]](except.spec "14.5 Exception specifications")[.](#temp.explicit-6.sentence-2)
|
||
|
||
[*Example [2](#temp.explicit-example-2)*: template<typename T> T var = {};template float var<float>; // OK, instantiated variable has type floattemplate int var<int[16]>[]; // OK, absence of major array bound is permittedtemplate int *var<int>; // error: instantiated variable has type inttemplate<typename T> auto av = T();template int av<int>; // OK, variable with type int can be redeclared with type autotemplate<typename T> auto f() {}template void f<int>(); // error: function with deduced return type// redeclared with non-deduced return type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")) â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
Despite its syntactic form, the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable[.](#temp.explicit-6.sentence-3)
|
||
|
||
[7](#temp.explicit-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7010)
|
||
|
||
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[.](#temp.explicit-7.sentence-1)
|
||
|
||
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[.](#temp.explicit-7.sentence-2)
|
||
|
||
[8](#temp.explicit-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7021)
|
||
|
||
[*Note [2](#temp.explicit-note-2)*:
|
||
|
||
An explicit instantiation of a constrained template needs
|
||
to satisfy that template's associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#temp.explicit-8.sentence-1)
|
||
|
||
The satisfaction of constraints is determined
|
||
when forming the template name of an explicit instantiation
|
||
in which all template arguments are specified ([[temp.names]](temp.names "13.3 Names of template specializations")),
|
||
or, for explicit instantiations 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[.](#temp.explicit-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[9](#temp.explicit-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7034)
|
||
|
||
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.decl "13.5.3 Constrained declarations"), [[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")),
|
||
except as described below[.](#temp.explicit-9.sentence-1)
|
||
|
||
[*Note [3](#temp.explicit-note-3)*:
|
||
|
||
In addition, it will typically be an explicit instantiation of certainimplementation-dependent data about the class[.](#temp.explicit-9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[10](#temp.explicit-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7051)
|
||
|
||
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[.](#temp.explicit-10.sentence-1)
|
||
|
||
[11](#temp.explicit-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7057)
|
||
|
||
An explicit instantiation of a prospective destructor ([[class.dtor]](class.dtor "11.4.7 Destructors"))
|
||
shall correspond to the selected destructor of the class[.](#temp.explicit-11.sentence-1)
|
||
|
||
[12](#temp.explicit-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7061)
|
||
|
||
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[.](#temp.explicit-12.sentence-1)
|
||
|
||
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](#temp.inst "13.9.2 Implicit instantiation [temp.inst]") 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[.](#temp.explicit-12.sentence-2)
|
||
|
||
[*Note [4](#temp.explicit-note-4)*:
|
||
|
||
This rule does apply to inline functions even though an
|
||
explicit instantiation declaration of such an entity has no other normative
|
||
effect[.](#temp.explicit-12.sentence-3)
|
||
|
||
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[.](#temp.explicit-12.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
An explicit instantiation declaration shall not name a specialization of a
|
||
template with internal linkage[.](#temp.explicit-12.sentence-5)
|
||
|
||
[13](#temp.explicit-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7080)
|
||
|
||
An explicit instantiation does not constitute a use of a default argument,
|
||
so default argument instantiation is not done[.](#temp.explicit-13.sentence-1)
|
||
|
||
[*Example [3](#temp.explicit-example-3)*: 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](#temp.expl.spec) Explicit specialization [[temp.expl.spec]](temp.expl.spec)
|
||
|
||
[1](#temp.expl.spec-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7093)
|
||
|
||
An explicit specialization of any of the following:
|
||
|
||
- [(1.1)](#temp.expl.spec-1.1)
|
||
|
||
function template
|
||
|
||
- [(1.2)](#temp.expl.spec-1.2)
|
||
|
||
class template
|
||
|
||
- [(1.3)](#temp.expl.spec-1.3)
|
||
|
||
variable template
|
||
|
||
- [(1.4)](#temp.expl.spec-1.4)
|
||
|
||
member function of a class template
|
||
|
||
- [(1.5)](#temp.expl.spec-1.5)
|
||
|
||
static data member of a class template
|
||
|
||
- [(1.6)](#temp.expl.spec-1.6)
|
||
|
||
member class of a class template
|
||
|
||
- [(1.7)](#temp.expl.spec-1.7)
|
||
|
||
member enumeration of a class template
|
||
|
||
- [(1.8)](#temp.expl.spec-1.8)
|
||
|
||
member class template of a class or class template
|
||
|
||
- [(1.9)](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-1.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[2](#temp.expl.spec-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]")[.](#temp.expl.spec-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[.](#temp.expl.spec-2.sentence-2)
|
||
|
||
[3](#temp.expl.spec-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"))[.](#temp.expl.spec-3.sentence-1)
|
||
|
||
[4](#temp.expl.spec-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"))[.](#temp.expl.spec-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[.](#temp.expl.spec-4.sentence-2)
|
||
|
||
[*Note [1](#temp.expl.spec-note-1)*:
|
||
|
||
A declaration, but not a definition of the template is needed[.](#temp.expl.spec-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[.](#temp.expl.spec-4.sentence-4)
|
||
|
||
[*Example [2](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-5.sentence-2)
|
||
|
||
[6](#temp.expl.spec-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[.](#temp.expl.spec-6.sentence-1)
|
||
|
||
The definition of the class template explicit specialization
|
||
shall be reachable from the definition of any member of it[.](#temp.expl.spec-6.sentence-2)
|
||
|
||
The definition of an explicitly specialized class is unrelated to the
|
||
definition of a generated specialization[.](#temp.expl.spec-6.sentence-3)
|
||
|
||
That is, its members need
|
||
not have the same names, types, etc. as the members of a generated
|
||
specialization[.](#temp.expl.spec-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[.](#temp.expl.spec-6.sentence-5)
|
||
|
||
The same is true when defining a member of an explicitly specialized member
|
||
class[.](#temp.expl.spec-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[.](#temp.expl.spec-6.sentence-7)
|
||
|
||
[*Example [3](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-7.sentence-2)
|
||
|
||
An implicit instantiation is never generated for an explicit specialization
|
||
that is declared but not defined[.](#temp.expl.spec-7.sentence-3)
|
||
|
||
[*Example [4](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-8.sentence-2)
|
||
|
||
[9](#temp.expl.spec-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7328)
|
||
|
||
[*Note [2](#temp.expl.spec-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"))[.](#temp.expl.spec-9.sentence-1)
|
||
|
||
[*Example [5](#temp.expl.spec-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](#temp.expl.spec-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7344)
|
||
|
||
[*Note [3](#temp.expl.spec-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"))[.](#temp.expl.spec-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[.](#temp.expl.spec-10.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[11](#temp.expl.spec-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"))[.](#temp.expl.spec-11.sentence-1)
|
||
|
||
[12](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-12.sentence-2)
|
||
|
||
[*Example [6](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-13.sentence-1)
|
||
|
||
[*Note [4](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-14.sentence-1)
|
||
|
||
An explicit specialization of a member or member template is specified using the
|
||
syntax for explicit specialization[.](#temp.expl.spec-14.sentence-2)
|
||
|
||
[*Example [7](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-15.sentence-2)
|
||
|
||
[*Example [8](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-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[.](#temp.expl.spec-16.sentence-3)
|
||
|
||
[*Example [9](#temp.expl.spec-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](#temp.expl.spec-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[.](#temp.expl.spec-17.sentence-1)
|
||
|
||
[18](#temp.expl.spec-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7500)
|
||
|
||
An explicit specialization declaration shall not be a friend declaration[.](#temp.expl.spec-18.sentence-1)
|
||
|
||
[19](#temp.expl.spec-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)](#temp.expl.spec-19.1)
|
||
|
||
the explicit specialization of a function template;
|
||
|
||
- [(19.2)](#temp.expl.spec-19.2)
|
||
|
||
the explicit specialization of a member function template;
|
||
|
||
- [(19.3)](#temp.expl.spec-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[.](#temp.expl.spec-19.sentence-1)
|
||
[*Note [5](#temp.expl.spec-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[.](#temp.expl.spec-19.3.sentence-2)
|
||
â *end note*]
|