Init
This commit is contained in:
412
cppdraft/temp/inst.md
Normal file
412
cppdraft/temp/inst.md
Normal file
@@ -0,0 +1,412 @@
|
||||
[temp.inst]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#temp.inst)
|
||||
|
||||
### 13.9.2 Implicit instantiation [temp.inst]
|
||||
|
||||
[1](#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)](#1.1)
|
||||
|
||||
an inline function,
|
||||
|
||||
- [(1.2)](#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)](#1.3)
|
||||
|
||||
a potentially-constant variable ([[expr.const]](expr.const "7.7 Constant expressions")), or
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
a specialization of a templated class[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#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"))[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
[*Note [2](#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[.](#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[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#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"))[.](#2.sentence-4)
|
||||
|
||||
[*Example [2](#example-2)*: template<class T> class X;
|
||||
X<char> ch; // error: incomplete type X<char> â *end example*]
|
||||
|
||||
[*Note [3](#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*)[.](#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[.](#2.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6564)
|
||||
|
||||
The implicit instantiation of a class template specialization causes
|
||||
|
||||
- [(3.1)](#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)](#3.2)
|
||||
|
||||
the implicit instantiation of the definitions of
|
||||
deleted member functions,
|
||||
unscoped member enumerations, and
|
||||
member anonymous unions[.](#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[.](#3.sentence-2)
|
||||
|
||||
[*Example [3](#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[.](#3.sentence-3)
|
||||
|
||||
[*Example [4](#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[.](#3.sentence-4)
|
||||
|
||||
(It is not defined
|
||||
but noted as being associated with a definition in Outer<T, U>[.](#3.sentence-5))
|
||||
|
||||
#2
|
||||
is also a redeclaration of #1a[.](#3.sentence-6)
|
||||
|
||||
It is noted as associated with a definition,
|
||||
so it is an invalid redeclaration of the same partial specialization[.](#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](#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[.](#4.sentence-1)
|
||||
|
||||
[5](#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[.](#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[.](#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[.](#5.sentence-3)
|
||||
|
||||
[*Note [4](#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[.](#5.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6664)
|
||||
|
||||
[*Example [5](#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[.](#6.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[7](#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[.](#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[.](#7.sentence-2)
|
||||
|
||||
[8](#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[.](#8.sentence-1)
|
||||
|
||||
[*Example [6](#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](#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[.](#9.sentence-1)
|
||||
|
||||
[*Example [7](#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](#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"))[.](#10.sentence-1)
|
||||
|
||||
[11](#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[.](#11.sentence-1)
|
||||
|
||||
[*Note [5](#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[.](#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[.](#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[.](#11.sentence-4)
|
||||
|
||||
The use of a default argument in a
|
||||
function call causes specializations in the default argument to be implicitly
|
||||
instantiated[.](#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[.](#11.sentence-6)
|
||||
|
||||
[12](#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[.](#12.sentence-1)
|
||||
|
||||
This analysis is called[*default argument instantiation*](#def:default_argument_instantiation "13.9.2 Implicit instantiation [temp.inst]")[.](#12.sentence-2)
|
||||
|
||||
The instantiated default argument is then used as the argument off[.](#12.sentence-3)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6802)
|
||||
|
||||
Each default argument is instantiated independently[.](#13.sentence-1)
|
||||
|
||||
[*Example [8](#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](#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"))[.](#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[.](#14.sentence-2)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6832)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
[[temp.point]](temp.point "13.8.4.1 Point of instantiation") defines the point of instantiation of a template specialization[.](#15.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[16](#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[.](#16.sentence-1)
|
||||
|
||||
The result of an infinite recursion in instantiation is undefined[.](#16.sentence-2)
|
||||
|
||||
[*Example [9](#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](#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[.](#17.sentence-1)
|
||||
|
||||
[*Note [7](#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"))[.](#17.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [10](#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[.](#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[.](#17.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [11](#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[.](#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[.](#17.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
Reference in New Issue
Block a user