This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

85
cppdraft/temp/alias.md Normal file
View File

@@ -0,0 +1,85 @@
[temp.alias]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.alias)
### 13.7.8 Alias templates [temp.alias]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4592)
A [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") in which the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") is an[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]") ([[dcl.pre]](dcl.pre "9.1Preamble")) declares the[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") to be an [*alias template*](#def:template,alias "13.7.8Alias templates[temp.alias]")[.](#1.sentence-1)
An alias template is a name for a family of
types[.](#1.sentence-2)
The name of the alias template is a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4599)
A
- [(2.1)](#2.1)
[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") that is not the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") or
- [(2.2)](#2.2)
[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")
that designates the specialization of
an alias template is equivalent to the associated type obtained by
substitution of its [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* for the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* in the [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") of
the alias template[.](#2.sentence-1)
Any other [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") that names a specialization of an alias template is
a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") for a type alias[.](#2.sentence-2)
[*Note [1](#note-1)*:
An alias template name is never deduced[.](#2.sentence-3)
— *end note*]
[*Example [1](#example-1)*: template<class T> struct Alloc { /* ... */ };template<class T> using Vec = vector<T, Alloc<T>>;
Vec<int> v; // same as vector<int, Alloc<int>> v;template<class T>void process(Vec<T>& v){ /* ... */ }template<class T>void process(vector<T, Alloc<T>>& w){ /* ... */ } // error: redefinitiontemplate<template<class> class TT>void f(TT<int>);
f(v); // error: Vec not deducedtemplate<template<class,class> class TT>void g(TT<int, Alloc<int>>);
g(v); // OK, TT = vector — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4644)
However, if the [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") is dependent, subsequent template
argument substitution still applies to the [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")[.](#3.sentence-1)
[*Example [2](#example-2)*: template<typename...> using void_t = void;template<typename T> void_t<typename T::foo> f();
f<int>(); // error: int does not have a nested type foo — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4655)
The [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") in an alias template declaration shall not refer to
the alias template being declared[.](#4.sentence-1)
The type produced by an alias template
specialization shall not directly or indirectly make use of that specialization[.](#4.sentence-2)
[*Example [3](#example-3)*: template <class T> struct A;template <class T> using B = typename A<T>::U;template <class T> struct A {typedef B<T> U;};
B<short> b; // error: instantiation of B<short> uses own type via A<short>::U — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4670)
The type of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") appearing in an alias template declaration
is different between instantiations of that template,
even when the [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") is not dependent[.](#5.sentence-1)
[*Example [4](#example-4)*: template <class T>using A = decltype([] { }); // A<int> and A<char> refer to different closure types — *end example*]

483
cppdraft/temp/arg.md Normal file
View File

@@ -0,0 +1,483 @@
[temp.arg]
# 13 Templates [[temp]](./#temp)
## 13.4 Template arguments [temp.arg]
### [13.4.1](#general) General [[temp.arg.general]](temp.arg.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1009)
The type and form of each [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") specified
in a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") or
in a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall match the type and form specified for the corresponding
parameter declared by the template in its[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")[.](#general-1.sentence-1)
When the parameter declared by the template is a[template parameter pack](temp.variadic#def:template_parameter_pack "13.7.4Variadic templates[temp.variadic]"), it will correspond to zero or more[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#general-1.sentence-2)
[*Example [1](#general-example-1)*: template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
Array<int> v1(20);typedef std::complex<double> dcomplex; // std::complex is a standard library template Array<dcomplex> v2(30);
Array<dcomplex> v3(40);
void bar() { v1[3] = 7;
v2[3] = v3.elem(4) = dcomplex(7,8);} — *end example*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1043)
The template argument list of a [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") is
a template argument list in which the nth template argument
has the value of
the nth template parameter of the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")[.](#general-2.sentence-1)
If the nth template parameter is
a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")),
the nth template argument is a pack expansion
whose pattern is the name of the template parameter pack[.](#general-2.sentence-2)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1053)
In a[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]"),
an ambiguity between a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") and an expression is resolved to a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),
regardless of the form of the corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")[.](#general-3.sentence-1)[109](#footnote-109 "There is no such ambiguity in a default template-argument because the form of the template-parameter determines the allowable forms of the template-argument.")
[*Example [2](#general-example-2)*: template<class T> void f();template<int I> void f();
void g() { f<int()>(); // int() is a type-id: call the first f()} — *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1081)
[*Note [1](#general-note-1)*:
Names used in a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") are subject to access control where they appear[.](#general-4.sentence-1)
Because a template parameter is not a class member,
no access control applies where the template parameter is used[.](#general-4.sentence-2)
— *end note*]
[*Example [3](#general-example-3)*: template<class T> class X {static T t;};
class Y {private:struct S { /* ... */ };
X<S> x; // OK, S is accessible// X<Y::S> has a static member of type Y::S// OK, even though Y::S is private};
X<Y::S> y; // error: S not accessible — *end example*]
For a template argument that is a class type or a class template,
the template definition has no special access rights
to the members of the template argument[.](#general-4.sentence-3)
[*Example [4](#general-example-4)*: template <template <class TT> class T> class A {typename T<int>::S s;};
template <class U> class B {private:struct S { /* ... */ };};
A<B> b; // error: A has no access to B::S — *end example*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1123)
When template argument packs or default template arguments are used,
a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") list can be empty[.](#general-5.sentence-1)
In that case the empty<> brackets shall still be used as the[*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")[.](#general-5.sentence-2)
[*Example [5](#general-example-5)*: template<class T = char> class String;
String<>* p; // OK, String<char> String* q; // syntax errortemplate<class ... Elements> class Tuple;
Tuple<>* t; // OK, Elements is empty Tuple* u; // syntax error — *end example*]
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1141)
An explicit destructor call ([[class.dtor]](class.dtor "11.4.7Destructors")) for an object that has a type
that is a class template specialization may explicitly specify the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#general-6.sentence-1)
[*Example [6](#general-example-6)*: template<class T> struct A {~A();};void f(A<int>* p, A<int>* q) { p->A<int>::~A(); // OK, destructor call q->A<int>::~A<int>(); // OK, destructor call} — *end example*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1157)
If the use of a template argument
gives rise to an ill-formed construct in the instantiation of a
template specialization, the program is ill-formed[.](#general-7.sentence-1)
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1162)
When name lookup for the component name of a[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") finds an overload set, both non-template functions in the overload
set and function templates in the overload set for
which the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* do not match the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are ignored[.](#general-8.sentence-1)
[*Note [2](#general-note-2)*:
If none of the function templates have matching[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s*,
the program is ill-formed[.](#general-8.sentence-2)
— *end note*]
[9](#general-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1178)
When a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") does not designate a function,
a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is[implicitly instantiated](temp.inst "13.9.2Implicit instantiation[temp.inst]") when the value of that default argument is needed[.](#general-9.sentence-1)
[*Example [7](#general-example-7)*: template<typename T, typename U = int> struct S { };
S<bool>* p; // the type of p is S<bool, int>*
The default argument for U is instantiated to form the type S<bool, int>*[.](#general-9.sentence-2)
— *end example*]
[10](#general-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1193)
A [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") followed by an ellipsis is
a [pack expansion](temp.variadic#def:pack_expansion "13.7.4Variadic templates[temp.variadic]")[.](#general-10.sentence-1)
[109)](#footnote-109)[109)](#footnoteref-109)
There is no such ambiguity in a default[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") because the form of the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") determines the allowable forms of the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")[.](#footnote-109.sentence-1)
### [13.4.2](#type) Type template arguments [[temp.arg.type]](temp.arg.type)
[1](#type-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1199)
A[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a type template parameter
shall be a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#type-1.sentence-1)
[2](#type-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1206)
[*Example [1](#type-example-1)*: template <class T> class X { };template <class T> void f(T t) { }struct { } unnamed_obj;
void f() {struct A { }; enum { e1 }; typedef struct { } B;
B b;
X<A> x1; // OK X<A*> x2; // OK X<B> x3; // OK f(e1); // OK f(unnamed_obj); // OK f(b); // OK} — *end example*]
[*Note [1](#type-note-1)*:
A template type argument can be an incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#type-2.sentence-1)
— *end note*]
### [13.4.3](#nontype) Constant template arguments [[temp.arg.nontype]](temp.arg.nontype)
[1](#nontype-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1233)
A template argument E for
a constant template parameter with declared type T shall be such that the invented declarationT x = E ; satisfies the semantic constraints for the definition of
a constexpr variable with static storage duration ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))[.](#nontype-1.sentence-1)
If T contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
or a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types")),
the type of the parameter is deduced from the above declaration[.](#nontype-1.sentence-2)
[*Note [1](#nontype-note-1)*:
E is a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") or
(for a default template argument) an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#nontype-1.sentence-3)
— *end note*]
If the parameter type thus deduced is not permitted
for a constant template parameter ([[temp.param]](temp.param "13.2Template parameters")),
the program is ill-formed[.](#nontype-1.sentence-4)
[2](#nontype-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1253)
The value of a constant template parameter P of (possibly deduced) type T is determined from its template argument A as follows[.](#nontype-2.sentence-1)
If T is not a class type andA is not a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),A shall be a converted constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
of type T; the value of P is A (as converted)[.](#nontype-2.sentence-2)
[3](#nontype-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1262)
Otherwise, a temporary variableconstexpr T v = A; is introduced[.](#nontype-3.sentence-1)
The lifetime of v ends immediately after initializing it and
any template parameter object (see below)[.](#nontype-3.sentence-2)
For each such variable,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") v is termed a [*candidate initializer*](#def:candidate_initializer "13.4.3Constant template arguments[temp.arg.nontype]")[.](#nontype-3.sentence-3)
[4](#nontype-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1274)
If T is a class type,
a template parameter object ([[temp.param]](temp.param "13.2Template parameters")) exists
that is constructed so as to be template-argument-equivalent to v;P denotes that template parameter object[.](#nontype-4.sentence-1)
P is copy-initialized from an unspecified candidate initializer
that is template-argument-equivalent to v[.](#nontype-4.sentence-2)
If, for the initialization from any candidate initializer,
- [(4.1)](#nontype-4.1)
the initialization would be ill-formed, or
- [(4.2)](#nontype-4.2)
the full-expression of an invented [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") for the initialization would not be a constant expression
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ([[expr.const]](expr.const "7.7Constant expressions")), or
- [(4.3)](#nontype-4.3)
the initialization would cause P to not be template-argument-equivalent ([[temp.type]](temp.type "13.6Type equivalence")) to v,
the program is ill-formed[.](#nontype-4.sentence-3)
[5](#nontype-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1294)
Otherwise, the value of P is that of v[.](#nontype-5.sentence-1)
[6](#nontype-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1297)
For a constant template parameter of reference or pointer type,
or for each non-static data member of reference or pointer type
in a constant template parameter of class type or subobject thereof,
the reference or pointer value shall not refer
or point to (respectively):
- [(6.1)](#nontype-6.1)
a temporary object ([[class.temporary]](class.temporary "6.8.7Temporary objects")),
- [(6.2)](#nontype-6.2)
a string literal object ([[lex.string]](lex.string "5.13.5String literals")),
- [(6.3)](#nontype-6.3)
the result of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")),
- [(6.4)](#nontype-6.4)
a predefined __func__ variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")), or
- [(6.5)](#nontype-6.5)
a subobject ([[intro.object]](intro.object "6.8.2Object model")) of one of the above[.](#nontype-6.sentence-1)
[7](#nontype-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1311)
[*Example [1](#nontype-example-1)*: template <int& r> class A{};extern int x;
A<x> a; // OKvoid f(int p) {constexpr int& r = p; // OK A<r> a; // error: a static constexpr int& variable cannot be initialized to refer to p here} — *end example*]
[8](#nontype-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1324)
[*Example [2](#nontype-example-2)*: template<const int* pci> struct X { /* ... */ };int ai[10];
X<ai> xi; // array to pointer and qualification conversionsstruct Y { /* ... */ };template<const Y& b> struct Z { /* ... */ };
Y y;
Z<y> z; // no conversion, but note extra cv-qualificationtemplate<int (&pa)[5]> struct W { /* ... */ };int b[5];
W<b> w; // no conversionvoid f(char);void f(int);
template<void (*pf)(int)> struct A { /* ... */ };
A<&f> a; // selects f(int)template<auto n> struct B { /* ... */ };
B<5> b1; // OK, template parameter type is int B<'a'> b2; // OK, template parameter type is char B<2.5> b3; // OK, template parameter type is double B<void(0)> b4; // error: template parameter type cannot be voidtemplate<int i> struct C { /* ... */ };
C<{ 42 }> c1; // OKstruct J1 { J1 *self = this;};
B<J1{}> j1; // error: initialization of template parameter object is not a constant expressionstruct J2 { J2 *self = this; constexpr J2() {}constexpr J2(const J2&) {}};
B<J2{}> j2; // error: template parameter object not template-argument-equivalent to introduced temporary — *end example*]
[9](#nontype-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1370)
[*Note [2](#nontype-note-2)*:
A [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") ([[lex.string]](lex.string "5.13.5String literals")) is
not an acceptable [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a constant template parameter of non-class type[.](#nontype-9.sentence-1)
[*Example [3](#nontype-example-3)*: template<class T, T p> class X {/* ... */};
X<const char*, "Studebaker"> x; // error: string literal object as [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") X<const char*, "Knope" + 1> x2; // error: subobject of string literal object as [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")const char p[] = "Vivisectionist";
X<const char*, p> y; // OKstruct A {constexpr A(const char*) {}};
X<A, "Pyrophoricity"> z; // OK, [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") is a constructor argument to A — *end example*]
— *end note*]
[10](#nontype-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1396)
[*Note [3](#nontype-note-3)*:
A temporary object
is not an acceptable[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") when the corresponding
template parameter
has reference type[.](#nontype-10.sentence-1)
[*Example [4](#nontype-example-4)*: template<const int& CRI> struct B { /* ... */ };
B<1> b1; // error: temporary would be required for template argumentint c = 1;
B<c> b2; // OKstruct X { int n; };struct Y { const int &r; };template<Y y> struct C { /* ... */ };
C<Y{X{1}.n}> c; // error: subobject of temporary object used to initialize// reference member of template parameter — *end example*]
— *end note*]
### [13.4.4](#template) Template template arguments [[temp.arg.template]](temp.arg.template)
[1](#template-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1424)
A[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a template
template parameter
shall be the name of a template[.](#template-1.sentence-1)
For a [*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a class template or alias template[.](#template-1.sentence-2)
For a [*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a variable template[.](#template-1.sentence-3)
For a [*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a concept[.](#template-1.sentence-4)
Only primary templates are considered when matching the template template
argument with the corresponding parameter; partial specializations are not
considered even if their parameter lists match that of the template template
parameter[.](#template-1.sentence-5)
[2](#template-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1441)
Any partial specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")) associated with the
primary template are considered when a
specialization based on the template template parameter is instantiated[.](#template-2.sentence-1)
If a specialization is not reachable from the point of instantiation,
and it would have been selected had it been reachable, the program is ill-formed,
no diagnostic required[.](#template-2.sentence-2)
[*Example [1](#template-example-1)*: template<class T> class A { // primary templateint x;};template<class T> class A<T*> { // partial specializationlong x;};template<template<class U> class V> class C { V<int> y;
V<int*> z;};
C<A> c; // V<int> within C<A> uses the primary template, so c.y.x has type int// V<int*> within C<A> uses the partial specialization, so c.z.x has type long — *end example*]
[3](#template-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1465)
A template template parameter P and
a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A are[*compatible*](#def:compatible,template_template_parameter_and_template_argument "13.4.4Template template arguments[temp.arg.template]") if
- [(3.1)](#template-3.1)
A denotes a class template or an alias template andP is a type template parameter,
- [(3.2)](#template-3.2)
A denotes a variable template andP is a variable template parameter, or
- [(3.3)](#template-3.3)
A denotes a concept andP is a concept template parameter[.](#template-3.sentence-1)
[4](#template-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1482)
A template [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A matches a template
template parameter P whenA and P are compatible andP is at least as specialized as A, ignoring constraints
on A if P is unconstrained[.](#template-4.sentence-1)
If P contains a template parameter pack, then A also matches P if each of A's template parameters
matches the corresponding template parameter declared in the[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of P[.](#template-4.sentence-2)
Two template parameters match if they are of the same kind,
for constant template parameters, their types are
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")), and for template template parameters,
each of their corresponding template parameters matches, recursively[.](#template-4.sentence-3)
When P's [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") contains a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") that declares a template parameter
pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), the template parameter pack will match zero or more template
parameters or template parameter packs declared in the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ofA with the same type and form as the template parameter pack declared in P (ignoring whether those template parameters are template parameter packs)[.](#template-4.sentence-4)
[*Example [2](#template-example-2)*: template<class T> class A { /* ... */ };template<class T, class U = T> class B { /* ... */ };template<class ... Types> class C { /* ... */ };template<auto n> class D { /* ... */ };template<template<class> class P> class X { /* ... */ };template<template<class ...> class Q> class Y { /* ... */ };template<template<int> class R> class Z { /* ... */ };
X<A> xa; // OK X<B> xb; // OK X<C> xc; // OK Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK Z<D> zd; // OK — *end example*]
[*Example [3](#template-example-3)*: template <class T> struct eval;
template <template <class, class...> class TT, class T1, class... Rest>struct eval<TT<T1, Rest...>> { };
template <class T1> struct A;template <class T1, class T2> struct B;template <int N> struct C;template <class T1, int N> struct D;template <class T1, class T2, int N = 17> struct E;
eval<A<int>> eA; // OK, matches partial specialization of eval eval<B<int, float>> eB; // OK, matches partial specialization of eval eval<C<17>> eC; // error: C does not match TT in partial specialization eval<D<int, 17>> eD; // error: D does not match TT in partial specialization eval<E<int, float>> eE; // error: E does not match TT in partial specialization — *end example*]
[*Example [4](#template-example-4)*: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.g(); };
template<template<C> class P> struct S { };
template<C> struct X { };template<D> struct Y { };template<typename T> struct Z { };
S<X> s1; // OK, X and P have equivalent constraints S<Y> s2; // error: P is not at least as specialized as Y S<Z> s3; // OK, P is at least as specialized as Z — *end example*]
[5](#template-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1559)
A template template parameter P is
at least as specialized as a template [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A if, given the following rewrite to two function templates,
the function template corresponding to P is at least as specialized as
the function template corresponding to A according to the [partial ordering rules
for function templates](temp.func.order "13.7.7.3Partial ordering of function templates[temp.func.order]")[.](#template-5.sentence-1)
Given an invented class template X with the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of A (including default arguments
and [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"), if any):
- [(5.1)](#template-5.1)
Each of the two function templates has the same template parameters
and [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") (if any),
respectively, as P or A[.](#template-5.1.sentence-1)
- [(5.2)](#template-5.2)
Each function template has a single function parameter
whose type is a specialization of X with template arguments corresponding to the template parameters
from the respective function template where,
for each [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") PP in the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of the function template,
a corresponding [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") AA is formed[.](#template-5.2.sentence-1)
If PP declares a template parameter pack,
then AA is the pack expansion PP... ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"));
otherwise, AA is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denoting PP[.](#template-5.2.sentence-2)
If the rewrite produces an invalid type,
then P is not at least as specialized as A[.](#template-5.sentence-3)

View File

@@ -0,0 +1,156 @@
[temp.arg.explicit]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.arg.explicit)
### 13.10.2 Explicit template argument specification [temp.arg.explicit]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7566)
Template arguments can be specified when referring to a function
template specialization that is not a specialization of a constructor template
by qualifying the function template
name with the list of[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* in the same way as[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are specified in uses of a class template specialization[.](#1.sentence-1)
[*Example [1](#example-1)*:
template<class T> void sort(Array<T>& v);void f(Array<dcomplex>& cv, Array<int>& ci) { sort<dcomplex>(cv); // sort(Array<dcomplex>&) sort<int>(ci); // sort(Array<int>&)} andtemplate<class U, class V> U convert(V v);
void g(double d) {int i = convert<int,double>(d); // int convert(double)char c = convert<char,double>(d); // char convert(double)}
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7595)
Template arguments shall not be specified
when referring to a specialization of
a constructor template ([[class.ctor]](class.ctor "11.4.5Constructors"), [[class.qual]](class.qual "6.5.5.2Class members"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7600)
A template argument list may be specified when referring to a specialization
of a function template
- [(3.1)](#3.1)
when a function is called,
- [(3.2)](#3.2)
when the address of a function is taken, when a function initializes a
reference to function, or when a pointer to member function is formed,
- [(3.3)](#3.3)
in an explicit specialization,
- [(3.4)](#3.4)
in an explicit instantiation, or
- [(3.5)](#3.5)
in a friend declaration[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7617)
Trailing template arguments that can be deduced ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) or
obtained from default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* may be omitted from the list of explicit [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#4.sentence-1)
[*Note [1](#note-1)*:
A trailing template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")) not otherwise deduced will be
deduced as an empty sequence of template arguments[.](#4.sentence-2)
— *end note*]
If all of the template arguments can be
deduced or obtained from default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*,
they may all be omitted;
in this case, the empty template argument list <> itself may also be omitted[.](#4.sentence-3)
[*Example [2](#example-2)*: template<class X, class Y> X f(Y);template<class X, class Y, class ... Z> X g(Y);void h() {int i = f<int>(5.6); // Y deduced as doubleint j = f(5.6); // error: X cannot be deduced f<void>(f<int, bool>); // Y for outer f deduced as int (*)(bool) f<void>(f<int>); // error: f<int> does not denote a single function template specializationint k = g<int>(5.6); // Y deduced as double; Z deduced as an empty sequence f<void>(g<int, bool>); // Y for outer f deduced as int (*)(bool),// Z deduced as an empty sequence} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7646)
[*Note [2](#note-2)*:
An empty template argument list can be used to indicate that a given
use refers to a specialization of a function template even when a
non-template function ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) is visible that would otherwise be used[.](#5.sentence-1)
For example:template <class T> int f(T); // #1int f(int); // #2int k = f(1); // uses #2int l = f<>(1); // uses #1
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7660)
Template arguments that are present shall be specified in the declaration
order of their corresponding template parameters[.](#6.sentence-1)
The template argument list shall not specify more[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* than there are corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* unless one of the [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* declares a template
parameter pack[.](#6.sentence-2)
[*Example [3](#example-3)*: template<class X, class Y, class Z> X f(Y,Z);template<class ... Args> void f2();void g() { f<int,const char*,double>("aa",3.0);
f<int,const char*>("aa",3.0); // Z deduced as double f<int>("aa",3.0); // Y deduced as const char*; Z deduced as double f("aa",3.0); // error: X cannot be deduced f2<char, short, int, long>(); // OK} — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7683)
Implicit conversions ([[conv]](conv "7.3Standard conversions")) will be performed on a function argument
to convert it to the type of the corresponding function parameter if
the parameter type contains no template parameters
that participate in template argument deduction[.](#7.sentence-1)
[*Note [3](#note-3)*:
Template parameters do not participate in template argument deduction if
they are explicitly specified[.](#7.sentence-2)
For example,
template<class T> void f(T);
class Complex { Complex(double);};
void g() { f<Complex>(1); // OK, means f<Complex>(Complex(1))} — *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7706)
[*Note [4](#note-4)*:
Because the explicit template argument list follows the function
template name, and because
constructor templates ([[class.ctor]](class.ctor "11.4.5Constructors")) are named without using a
function name ([[class.qual]](class.qual "6.5.5.2Class members")), there is no way to provide an explicit
template argument list for these function templates[.](#8.sentence-1)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7715)
Template argument deduction can extend the sequence of template
arguments corresponding to a template parameter pack, even when the
sequence contains explicitly specified template arguments[.](#9.sentence-1)
[*Example [4](#example-4)*: template<class ... Types> void f(Types ... values);
void g() { f<int*, float*>(0, 0, 0); // Types deduced as the sequence int*, float*, int} — *end example*]

View File

@@ -0,0 +1,154 @@
[temp.arg.general]
# 13 Templates [[temp]](./#temp)
## 13.4 Template arguments [[temp.arg]](temp.arg#general)
### 13.4.1 General [temp.arg.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1009)
The type and form of each [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") specified
in a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") or
in a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall match the type and form specified for the corresponding
parameter declared by the template in its[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")[.](#1.sentence-1)
When the parameter declared by the template is a[template parameter pack](temp.variadic#def:template_parameter_pack "13.7.4Variadic templates[temp.variadic]"), it will correspond to zero or more[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#1.sentence-2)
[*Example [1](#example-1)*: template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
Array<int> v1(20);typedef std::complex<double> dcomplex; // std::complex is a standard library template Array<dcomplex> v2(30);
Array<dcomplex> v3(40);
void bar() { v1[3] = 7;
v2[3] = v3.elem(4) = dcomplex(7,8);} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1043)
The template argument list of a [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") is
a template argument list in which the nth template argument
has the value of
the nth template parameter of the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")[.](#2.sentence-1)
If the nth template parameter is
a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")),
the nth template argument is a pack expansion
whose pattern is the name of the template parameter pack[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1053)
In a[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]"),
an ambiguity between a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") and an expression is resolved to a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),
regardless of the form of the corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")[.](#3.sentence-1)[109](#footnote-109 "There is no such ambiguity in a default template-argument because the form of the template-parameter determines the allowable forms of the template-argument.")
[*Example [2](#example-2)*: template<class T> void f();template<int I> void f();
void g() { f<int()>(); // int() is a type-id: call the first f()} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1081)
[*Note [1](#note-1)*:
Names used in a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") are subject to access control where they appear[.](#4.sentence-1)
Because a template parameter is not a class member,
no access control applies where the template parameter is used[.](#4.sentence-2)
— *end note*]
[*Example [3](#example-3)*: template<class T> class X {static T t;};
class Y {private:struct S { /* ... */ };
X<S> x; // OK, S is accessible// X<Y::S> has a static member of type Y::S// OK, even though Y::S is private};
X<Y::S> y; // error: S not accessible — *end example*]
For a template argument that is a class type or a class template,
the template definition has no special access rights
to the members of the template argument[.](#4.sentence-3)
[*Example [4](#example-4)*: template <template <class TT> class T> class A {typename T<int>::S s;};
template <class U> class B {private:struct S { /* ... */ };};
A<B> b; // error: A has no access to B::S — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1123)
When template argument packs or default template arguments are used,
a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") list can be empty[.](#5.sentence-1)
In that case the empty<> brackets shall still be used as the[*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")[.](#5.sentence-2)
[*Example [5](#example-5)*: template<class T = char> class String;
String<>* p; // OK, String<char> String* q; // syntax errortemplate<class ... Elements> class Tuple;
Tuple<>* t; // OK, Elements is empty Tuple* u; // syntax error — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1141)
An explicit destructor call ([[class.dtor]](class.dtor "11.4.7Destructors")) for an object that has a type
that is a class template specialization may explicitly specify the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#6.sentence-1)
[*Example [6](#example-6)*: template<class T> struct A {~A();};void f(A<int>* p, A<int>* q) { p->A<int>::~A(); // OK, destructor call q->A<int>::~A<int>(); // OK, destructor call} — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1157)
If the use of a template argument
gives rise to an ill-formed construct in the instantiation of a
template specialization, the program is ill-formed[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1162)
When name lookup for the component name of a[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") finds an overload set, both non-template functions in the overload
set and function templates in the overload set for
which the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* do not match the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are ignored[.](#8.sentence-1)
[*Note [2](#note-2)*:
If none of the function templates have matching[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s*,
the program is ill-formed[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1178)
When a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") does not designate a function,
a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is[implicitly instantiated](temp.inst "13.9.2Implicit instantiation[temp.inst]") when the value of that default argument is needed[.](#9.sentence-1)
[*Example [7](#example-7)*: template<typename T, typename U = int> struct S { };
S<bool>* p; // the type of p is S<bool, int>*
The default argument for U is instantiated to form the type S<bool, int>*[.](#9.sentence-2)
— *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1193)
A [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") followed by an ellipsis is
a [pack expansion](temp.variadic#def:pack_expansion "13.7.4Variadic templates[temp.variadic]")[.](#10.sentence-1)
[109)](#footnote-109)[109)](#footnoteref-109)
There is no such ambiguity in a default[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") because the form of the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") determines the allowable forms of the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")[.](#footnote-109.sentence-1)

View File

@@ -0,0 +1,177 @@
[temp.arg.nontype]
# 13 Templates [[temp]](./#temp)
## 13.4 Template arguments [[temp.arg]](temp.arg#nontype)
### 13.4.3 Constant template arguments [temp.arg.nontype]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1233)
A template argument E for
a constant template parameter with declared type T shall be such that the invented declarationT x = E ; satisfies the semantic constraints for the definition of
a constexpr variable with static storage duration ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))[.](#1.sentence-1)
If T contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
or a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types")),
the type of the parameter is deduced from the above declaration[.](#1.sentence-2)
[*Note [1](#note-1)*:
E is a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") or
(for a default template argument) an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#1.sentence-3)
— *end note*]
If the parameter type thus deduced is not permitted
for a constant template parameter ([[temp.param]](temp.param "13.2Template parameters")),
the program is ill-formed[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1253)
The value of a constant template parameter P of (possibly deduced) type T is determined from its template argument A as follows[.](#2.sentence-1)
If T is not a class type andA is not a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),A shall be a converted constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
of type T; the value of P is A (as converted)[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1262)
Otherwise, a temporary variableconstexpr T v = A; is introduced[.](#3.sentence-1)
The lifetime of v ends immediately after initializing it and
any template parameter object (see below)[.](#3.sentence-2)
For each such variable,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") v is termed a [*candidate initializer*](#def:candidate_initializer "13.4.3Constant template arguments[temp.arg.nontype]")[.](#3.sentence-3)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1274)
If T is a class type,
a template parameter object ([[temp.param]](temp.param "13.2Template parameters")) exists
that is constructed so as to be template-argument-equivalent to v;P denotes that template parameter object[.](#4.sentence-1)
P is copy-initialized from an unspecified candidate initializer
that is template-argument-equivalent to v[.](#4.sentence-2)
If, for the initialization from any candidate initializer,
- [(4.1)](#4.1)
the initialization would be ill-formed, or
- [(4.2)](#4.2)
the full-expression of an invented [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") for the initialization would not be a constant expression
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ([[expr.const]](expr.const "7.7Constant expressions")), or
- [(4.3)](#4.3)
the initialization would cause P to not be template-argument-equivalent ([[temp.type]](temp.type "13.6Type equivalence")) to v,
the program is ill-formed[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1294)
Otherwise, the value of P is that of v[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1297)
For a constant template parameter of reference or pointer type,
or for each non-static data member of reference or pointer type
in a constant template parameter of class type or subobject thereof,
the reference or pointer value shall not refer
or point to (respectively):
- [(6.1)](#6.1)
a temporary object ([[class.temporary]](class.temporary "6.8.7Temporary objects")),
- [(6.2)](#6.2)
a string literal object ([[lex.string]](lex.string "5.13.5String literals")),
- [(6.3)](#6.3)
the result of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")),
- [(6.4)](#6.4)
a predefined __func__ variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")), or
- [(6.5)](#6.5)
a subobject ([[intro.object]](intro.object "6.8.2Object model")) of one of the above[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1311)
[*Example [1](#example-1)*: template <int& r> class A{};extern int x;
A<x> a; // OKvoid f(int p) {constexpr int& r = p; // OK A<r> a; // error: a static constexpr int& variable cannot be initialized to refer to p here} — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1324)
[*Example [2](#example-2)*: template<const int* pci> struct X { /* ... */ };int ai[10];
X<ai> xi; // array to pointer and qualification conversionsstruct Y { /* ... */ };template<const Y& b> struct Z { /* ... */ };
Y y;
Z<y> z; // no conversion, but note extra cv-qualificationtemplate<int (&pa)[5]> struct W { /* ... */ };int b[5];
W<b> w; // no conversionvoid f(char);void f(int);
template<void (*pf)(int)> struct A { /* ... */ };
A<&f> a; // selects f(int)template<auto n> struct B { /* ... */ };
B<5> b1; // OK, template parameter type is int B<'a'> b2; // OK, template parameter type is char B<2.5> b3; // OK, template parameter type is double B<void(0)> b4; // error: template parameter type cannot be voidtemplate<int i> struct C { /* ... */ };
C<{ 42 }> c1; // OKstruct J1 { J1 *self = this;};
B<J1{}> j1; // error: initialization of template parameter object is not a constant expressionstruct J2 { J2 *self = this; constexpr J2() {}constexpr J2(const J2&) {}};
B<J2{}> j2; // error: template parameter object not template-argument-equivalent to introduced temporary — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1370)
[*Note [2](#note-2)*:
A [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") ([[lex.string]](lex.string "5.13.5String literals")) is
not an acceptable [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a constant template parameter of non-class type[.](#9.sentence-1)
[*Example [3](#example-3)*: template<class T, T p> class X {/* ... */};
X<const char*, "Studebaker"> x; // error: string literal object as [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") X<const char*, "Knope" + 1> x2; // error: subobject of string literal object as [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")const char p[] = "Vivisectionist";
X<const char*, p> y; // OKstruct A {constexpr A(const char*) {}};
X<A, "Pyrophoricity"> z; // OK, [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") is a constructor argument to A — *end example*]
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1396)
[*Note [3](#note-3)*:
A temporary object
is not an acceptable[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") when the corresponding
template parameter
has reference type[.](#10.sentence-1)
[*Example [4](#example-4)*: template<const int& CRI> struct B { /* ... */ };
B<1> b1; // error: temporary would be required for template argumentint c = 1;
B<c> b2; // OKstruct X { int n; };struct Y { const int &r; };template<Y y> struct C { /* ... */ };
C<Y{X{1}.n}> c; // error: subobject of temporary object used to initialize// reference member of template parameter — *end example*]
— *end note*]

View File

@@ -0,0 +1,137 @@
[temp.arg.template]
# 13 Templates [[temp]](./#temp)
## 13.4 Template arguments [[temp.arg]](temp.arg#template)
### 13.4.4 Template template arguments [temp.arg.template]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1424)
A[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a template
template parameter
shall be the name of a template[.](#1.sentence-1)
For a [*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a class template or alias template[.](#1.sentence-2)
For a [*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a variable template[.](#1.sentence-3)
For a [*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2Template parameters[temp.param]"),
the name shall denote a concept[.](#1.sentence-4)
Only primary templates are considered when matching the template template
argument with the corresponding parameter; partial specializations are not
considered even if their parameter lists match that of the template template
parameter[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1441)
Any partial specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")) associated with the
primary template are considered when a
specialization based on the template template parameter is instantiated[.](#2.sentence-1)
If a specialization is not reachable from the point of instantiation,
and it would have been selected had it been reachable, the program is ill-formed,
no diagnostic required[.](#2.sentence-2)
[*Example [1](#example-1)*: template<class T> class A { // primary templateint x;};template<class T> class A<T*> { // partial specializationlong x;};template<template<class U> class V> class C { V<int> y;
V<int*> z;};
C<A> c; // V<int> within C<A> uses the primary template, so c.y.x has type int// V<int*> within C<A> uses the partial specialization, so c.z.x has type long — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1465)
A template template parameter P and
a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A are[*compatible*](#def:compatible,template_template_parameter_and_template_argument "13.4.4Template template arguments[temp.arg.template]") if
- [(3.1)](#3.1)
A denotes a class template or an alias template andP is a type template parameter,
- [(3.2)](#3.2)
A denotes a variable template andP is a variable template parameter, or
- [(3.3)](#3.3)
A denotes a concept andP is a concept template parameter[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1482)
A template [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A matches a template
template parameter P whenA and P are compatible andP is at least as specialized as A, ignoring constraints
on A if P is unconstrained[.](#4.sentence-1)
If P contains a template parameter pack, then A also matches P if each of A's template parameters
matches the corresponding template parameter declared in the[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of P[.](#4.sentence-2)
Two template parameters match if they are of the same kind,
for constant template parameters, their types are
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")), and for template template parameters,
each of their corresponding template parameters matches, recursively[.](#4.sentence-3)
When P's [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") contains a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") that declares a template parameter
pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), the template parameter pack will match zero or more template
parameters or template parameter packs declared in the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ofA with the same type and form as the template parameter pack declared in P (ignoring whether those template parameters are template parameter packs)[.](#4.sentence-4)
[*Example [2](#example-2)*: template<class T> class A { /* ... */ };template<class T, class U = T> class B { /* ... */ };template<class ... Types> class C { /* ... */ };template<auto n> class D { /* ... */ };template<template<class> class P> class X { /* ... */ };template<template<class ...> class Q> class Y { /* ... */ };template<template<int> class R> class Z { /* ... */ };
X<A> xa; // OK X<B> xb; // OK X<C> xc; // OK Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK Z<D> zd; // OK — *end example*]
[*Example [3](#example-3)*: template <class T> struct eval;
template <template <class, class...> class TT, class T1, class... Rest>struct eval<TT<T1, Rest...>> { };
template <class T1> struct A;template <class T1, class T2> struct B;template <int N> struct C;template <class T1, int N> struct D;template <class T1, class T2, int N = 17> struct E;
eval<A<int>> eA; // OK, matches partial specialization of eval eval<B<int, float>> eB; // OK, matches partial specialization of eval eval<C<17>> eC; // error: C does not match TT in partial specialization eval<D<int, 17>> eD; // error: D does not match TT in partial specialization eval<E<int, float>> eE; // error: E does not match TT in partial specialization — *end example*]
[*Example [4](#example-4)*: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.g(); };
template<template<C> class P> struct S { };
template<C> struct X { };template<D> struct Y { };template<typename T> struct Z { };
S<X> s1; // OK, X and P have equivalent constraints S<Y> s2; // error: P is not at least as specialized as Y S<Z> s3; // OK, P is at least as specialized as Z — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1559)
A template template parameter P is
at least as specialized as a template [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") A if, given the following rewrite to two function templates,
the function template corresponding to P is at least as specialized as
the function template corresponding to A according to the [partial ordering rules
for function templates](temp.func.order "13.7.7.3Partial ordering of function templates[temp.func.order]")[.](#5.sentence-1)
Given an invented class template X with the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of A (including default arguments
and [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"), if any):
- [(5.1)](#5.1)
Each of the two function templates has the same template parameters
and [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") (if any),
respectively, as P or A[.](#5.1.sentence-1)
- [(5.2)](#5.2)
Each function template has a single function parameter
whose type is a specialization of X with template arguments corresponding to the template parameters
from the respective function template where,
for each [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") PP in the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") of the function template,
a corresponding [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") AA is formed[.](#5.2.sentence-1)
If PP declares a template parameter pack,
then AA is the pack expansion PP... ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"));
otherwise, AA is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") denoting PP[.](#5.2.sentence-2)
If the rewrite produces an invalid type,
then P is not at least as specialized as A[.](#5.sentence-3)

30
cppdraft/temp/arg/type.md Normal file
View File

@@ -0,0 +1,30 @@
[temp.arg.type]
# 13 Templates [[temp]](./#temp)
## 13.4 Template arguments [[temp.arg]](temp.arg#type)
### 13.4.2 Type template arguments [temp.arg.type]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1199)
A[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a type template parameter
shall be a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1206)
[*Example [1](#example-1)*: template <class T> class X { };template <class T> void f(T t) { }struct { } unnamed_obj;
void f() {struct A { }; enum { e1 }; typedef struct { } B;
B b;
X<A> x1; // OK X<A*> x2; // OK X<B> x3; // OK f(e1); // OK f(unnamed_obj); // OK f(b); // OK} — *end example*]
[*Note [1](#note-1)*:
A template type argument can be an incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#2.sentence-1)
— *end note*]

229
cppdraft/temp/class.md Normal file
View File

@@ -0,0 +1,229 @@
[temp.class]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.class)
### 13.7.2 Class templates [temp.class]
#### [13.7.2.1](#general) General [[temp.class.general]](temp.class.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2650)
A[*class template*](#def:template,class "13.7.2.1General[temp.class.general]") defines the layout and operations
for an unbounded set of related types[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2656)
[*Example [1](#general-example-1)*:
It is possible for a single class templateList to provide an unbounded set of class definitions:
one class List<T> for every type T,
each describing a linked list of elements of type T[.](#general-2.sentence-1)
Similarly, a class template Array describing a contiguous,
dynamic array can be defined like this:template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
The prefix template<class T> specifies that a template is being declared and that a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") T can be used in the declaration[.](#general-2.sentence-3)
In other words,Array is a parameterized type withT as its parameter[.](#general-2.sentence-4)
— *end example*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2686)
[*Note [1](#general-note-1)*:
When a member of a class
template is defined outside of the class template definition,
the member definition is defined as a template definition with the[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") equivalent to that
of the class template[.](#general-3.sentence-1)
The names of the template parameters used in the definition of the member
can differ from the template parameter names used in the class
template definition[.](#general-3.sentence-2)
The class template name in the member definition is followed by
the template argument list of the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template arguments"))[.](#general-3.sentence-3)
[*Example [2](#general-example-2)*: template<class T1, class T2> struct A {void f1(); void f2();};
template<class T2, class T1> void A<T2,T1>::f1() { } // OKtemplate<class T2, class T1> void A<T1,T2>::f2() { } // error
template<class ... Types> struct B {void f3(); void f4();};
template<class ... Types> void B<Types ...>::f3() { } // OKtemplate<class ... Types> void B<Types>::f4() { } // error
template<typename T> concept C = true;template<typename T> concept D = true;
template<C T> struct S {void f(); void g(); void h(); template<D U> struct Inner;};
template<C A> void S<A>::f() { } // OK, [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* matchtemplate<typename T> void S<T>::g() { } // error: no matching declaration for S<T>template<typename T> requires C<T> // ill-formed, no diagnostic required: [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* arevoid S<T>::h() { } // functionally equivalent but not equivalenttemplate<C X> template<D Y>struct S<X>::Inner { }; // OK — *end example*]
— *end note*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2742)
In a partial specialization,
explicit specialization or
explicit instantiation of a class template,
the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"))[.](#general-4.sentence-1)
#### [13.7.2.2](#temp.mem.func) Member functions of class templates [[temp.mem.func]](temp.mem.func)
[1](#temp.mem.func-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2751)
A member function
of a class template
may be defined outside of the class
template definition in which it is declared[.](#temp.mem.func-1.sentence-1)
[*Example [1](#temp.mem.func-example-1)*: template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
declares three member functions of a class template[.](#temp.mem.func-1.sentence-2)
The subscript function can be defined like this:template<class T> T& Array<T>::operator[](int i) {if (i<0 || sz<=i) error("Array: range error"); return v[i];}
A constrained member function can be defined out of line:template<typename T> concept C = requires {typename T::type;};
template<typename T> struct S {void f() requires C<T>; void g() requires C<T>;};
template<typename T>void S<T>::f() requires C<T> { } // OKtemplate<typename T>void S<T>::g() { } // error: no matching function in S<T>
— *end example*]
[2](#temp.mem.func-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2796)
The[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* for a member function of a class template are determined by the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* of the type of the object for which the member function is called[.](#temp.mem.func-2.sentence-1)
[*Example [2](#temp.mem.func-example-2)*:
The[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") forArray<T>::operator[] will be determined by theArray to which the subscripting operation is applied[.](#temp.mem.func-2.sentence-2)
Array<int> v1(20);
Array<dcomplex> v2(30);
v1[3] = 7; // Array<int>::operator[] v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[] — *end example*]
#### [13.7.2.3](#temp.deduct.guide) Deduction guides [[temp.deduct.guide]](temp.deduct.guide)
[1](#temp.deduct.guide-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2823)
Deduction guides are used
when a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") appears as a type specifier
for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))[.](#temp.deduct.guide-1.sentence-1)
Deduction guides are not found by name lookup[.](#temp.deduct.guide-1.sentence-2)
Instead, when performing class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction")),
all reachable deduction guides declared for the class template are considered[.](#temp.deduct.guide-1.sentence-3)
[deduction-guide:](#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]")
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")opt ;
[2](#temp.deduct.guide-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2837)
[*Example [1](#temp.deduct.guide-example-1)*: template<class T, class D = int>struct S { T data;};template<class U> S(U) -> S<typename U::type>;
struct A {using type = short; operator type();};
S x{A()}; // x is of type S<short, int> — *end example*]
[3](#temp.deduct.guide-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2855)
The same restrictions apply
to the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of a deduction guide
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of
a deduction guide[.](#temp.deduct.guide-3.sentence-1)
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") shall name a class template specialization[.](#temp.deduct.guide-3.sentence-2)
The [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#temp.deduct.guide-3.sentence-3)
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]") shall inhabit the scope
to which the corresponding class template belongs
and, for a member class template, have the same access[.](#temp.deduct.guide-3.sentence-4)
Two deduction guide declarations
for the same class template
shall not have equivalent [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")*s* if either is reachable from the other[.](#temp.deduct.guide-3.sentence-5)
#### [13.7.2.4](#temp.mem.class) Member classes of class templates [[temp.mem.class]](temp.mem.class)
[1](#temp.mem.class-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2880)
A member class of a class template may be defined outside the class template
definition in which it is declared[.](#temp.mem.class-1.sentence-1)
[*Note [1](#temp.mem.class-note-1)*:
The member class must be defined before its first use that requires
an instantiation ([[temp.inst]](temp.inst "13.9.2Implicit instantiation"))[.](#temp.mem.class-1.sentence-2)
For example,template<class T> struct A {class B;};
A<int>::B* b1; // OK, requires A to be defined but not A::Btemplate<class T> class A<T>::B { };
A<int>::B b2; // OK, requires A::B to be defined
— *end note*]
#### [13.7.2.5](#temp.static) Static data members of class templates [[temp.static]](temp.static)
[1](#temp.static-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2899)
A definition for a static data member or static data member template may be
provided in a namespace scope enclosing the definition of the static member's
class template[.](#temp.static-1.sentence-1)
[*Example [1](#temp.static-example-1)*: template<class T> class X {static T s;};template<class T> T X<T>::s = 0;
struct limits {template<class T>static const T min; // declaration};
template<class T>const T limits::min = { }; // definition — *end example*]
[2](#temp.static-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2921)
An explicit specialization of a static data member declared as an array of unknown
bound can have a different bound from its definition, if any[.](#temp.static-2.sentence-1)
[*Example [2](#temp.static-example-2)*: template <class T> struct A {static int i[];};template <class T> int A<T>::i[4]; // 4 elementstemplate <> int A<int>::i[] = { 1 }; // OK, 1 element — *end example*]
#### [13.7.2.6](#temp.mem.enum) Enumeration members of class templates [[temp.mem.enum]](temp.mem.enum)
[1](#temp.mem.enum-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2936)
An enumeration member of a class template may be defined outside the class
template definition[.](#temp.mem.enum-1.sentence-1)
[*Example [1](#temp.mem.enum-example-1)*: template<class T> struct A {enum E : T;};template<class T> enum A<T>::E : T { e1, e2 };
A<int>::E e = A<int>::e1; — *end example*]

View File

@@ -0,0 +1,80 @@
[temp.class.general]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.class.general)
### 13.7.2 Class templates [[temp.class]](temp.class#general)
#### 13.7.2.1 General [temp.class.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2650)
A[*class template*](#def:template,class "13.7.2.1General[temp.class.general]") defines the layout and operations
for an unbounded set of related types[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2656)
[*Example [1](#example-1)*:
It is possible for a single class templateList to provide an unbounded set of class definitions:
one class List<T> for every type T,
each describing a linked list of elements of type T[.](#2.sentence-1)
Similarly, a class template Array describing a contiguous,
dynamic array can be defined like this:template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
The prefix template<class T> specifies that a template is being declared and that a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") T can be used in the declaration[.](#2.sentence-3)
In other words,Array is a parameterized type withT as its parameter[.](#2.sentence-4)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2686)
[*Note [1](#note-1)*:
When a member of a class
template is defined outside of the class template definition,
the member definition is defined as a template definition with the[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") equivalent to that
of the class template[.](#3.sentence-1)
The names of the template parameters used in the definition of the member
can differ from the template parameter names used in the class
template definition[.](#3.sentence-2)
The class template name in the member definition is followed by
the template argument list of the [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template arguments"))[.](#3.sentence-3)
[*Example [2](#example-2)*: template<class T1, class T2> struct A {void f1(); void f2();};
template<class T2, class T1> void A<T2,T1>::f1() { } // OKtemplate<class T2, class T1> void A<T1,T2>::f2() { } // error
template<class ... Types> struct B {void f3(); void f4();};
template<class ... Types> void B<Types ...>::f3() { } // OKtemplate<class ... Types> void B<Types>::f4() { } // error
template<typename T> concept C = true;template<typename T> concept D = true;
template<C T> struct S {void f(); void g(); void h(); template<D U> struct Inner;};
template<C A> void S<A>::f() { } // OK, [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* matchtemplate<typename T> void S<T>::g() { } // error: no matching declaration for S<T>template<typename T> requires C<T> // ill-formed, no diagnostic required: [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* arevoid S<T>::h() { } // functionally equivalent but not equivalenttemplate<C X> template<D Y>struct S<X>::Inner { }; // OK — *end example*]
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2742)
In a partial specialization,
explicit specialization or
explicit instantiation of a class template,
the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"))[.](#4.sentence-1)

79
cppdraft/temp/concept.md Normal file
View File

@@ -0,0 +1,79 @@
[temp.concept]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.concept)
### 13.7.9 Concept definitions [temp.concept]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4684)
A [*concept*](#def:concept "13.7.9Concept definitions[temp.concept]") is a template
that defines constraints on its template arguments[.](#1.sentence-1)
[concept-definition:](#nt:concept-definition "13.7.9Concept definitions[temp.concept]")
concept [*concept-name*](#nt:concept-name "13.7.9Concept definitions[temp.concept]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt = [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") ;
[concept-name:](#nt:concept-name "13.7.9Concept definitions[temp.concept]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4698)
A [*concept-definition*](#nt:concept-definition "13.7.9Concept definitions[temp.concept]") declares a concept[.](#2.sentence-1)
Its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") becomes a [*concept-name*](#nt:concept-name "13.7.9Concept definitions[temp.concept]") referring to that concept
within its scope[.](#2.sentence-2)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the concept[.](#2.sentence-3)
[*Example [1](#example-1)*: template<typename T>concept C = requires(T x) {{ x == x } -> std::[convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<bool>;};
template<typename T>requires C<T> // C constrains f1(T) in [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") T f1(T x) { return x; }template<C T> // C, as a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"), constrains f2(T) T f2(T x) { return x; } — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4721)
A [*concept-definition*](#nt:concept-definition "13.7.9Concept definitions[temp.concept]") shall inhabit a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6Namespace scope"))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4725)
A concept shall not have [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]")[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4728)
A concept is not instantiated ([[temp.spec]](temp.spec "13.9Template instantiation and specialization"))[.](#5.sentence-1)
[*Note [1](#note-1)*:
A concept-id ([[temp.names]](temp.names "13.3Names of template specializations")) is evaluated as an expression[.](#5.sentence-2)
A concept cannot be
explicitly instantiated ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")),
explicitly specialized ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")),
or partially specialized ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"))[.](#5.sentence-3)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4738)
The [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") of a [*concept-definition*](#nt:concept-definition "13.7.9Concept definitions[temp.concept]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3Context dependence"))[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4742)
The first declared template parameter of a concept definition is its[*prototype parameter*](#def:prototype_parameter,concept "13.7.9Concept definitions[temp.concept]")[.](#7.sentence-1)
A [*type concept*](#def:concept,type "13.7.9Concept definitions[temp.concept]") is a concept whose prototype parameter
is a type template parameter[.](#7.sentence-2)

848
cppdraft/temp/constr.md Normal file
View File

@@ -0,0 +1,848 @@
[temp.constr]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [temp.constr]
### [13.5.1](#general) General [[temp.constr.general]](temp.constr.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1595)
[*Note [1](#general-note-1)*:
Subclause [temp.constr] defines the meaning of constraints on template arguments[.](#general-1.sentence-1)
The abstract syntax and satisfaction rules are defined
in [[temp.constr.constr]](#constr "13.5.2Constraints")[.](#general-1.sentence-2)
Constraints are associated with declarations in [[temp.constr.decl]](#decl "13.5.3Constrained declarations")[.](#general-1.sentence-3)
Declarations are partially ordered by their associated constraints ([[temp.constr.order]](#order "13.5.5Partial ordering by constraints"))[.](#general-1.sentence-4)
— *end note*]
### [13.5.2](#constr) Constraints [[temp.constr.constr]](temp.constr.constr)
#### [13.5.2.1](#constr.general) General [[temp.constr.constr.general]](temp.constr.constr.general)
[1](#constr.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610)
A [*constraint*](#def:constraint "13.5.2.1General[temp.constr.constr.general]") is a sequence of logical operations and
operands that specifies requirements on template arguments[.](#constr.general-1.sentence-1)
The operands of a logical operation are constraints[.](#constr.general-1.sentence-2)
There are five different kinds of constraints:
- [(1.1)](#constr.general-1.1)
conjunctions ([[temp.constr.op]](#op "13.5.2.2Logical operations")),
- [(1.2)](#constr.general-1.2)
disjunctions ([[temp.constr.op]](#op "13.5.2.2Logical operations")),
- [(1.3)](#constr.general-1.3)
atomic constraints ([[temp.constr.atomic]](#atomic "13.5.2.3Atomic constraints")),
- [(1.4)](#constr.general-1.4)
concept-dependent constraints ([[temp.constr.concept]](#concept "13.5.2.4Concept-dependent constraints")), and
- [(1.5)](#constr.general-1.5)
fold expanded constraints ([[temp.constr.fold]](#fold "13.5.2.5Fold expanded constraint"))[.](#constr.general-1.sentence-3)
[2](#constr.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623)
In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9Template instantiation and specialization")),
its [associated constraints](#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#constr.general-2.sentence-1)
[*Note [1](#constr.general-note-1)*:
Forming the name of a specialization of
a class template,
a variable template, or
an alias template ([[temp.names]](temp.names "13.3Names of template specializations"))
requires the satisfaction of its constraints[.](#constr.general-2.sentence-2)
[Overload resolution](over.match.viable "12.2.3Viable functions[over.match.viable]") requires the satisfaction of constraints
on functions and function templates[.](#constr.general-2.sentence-3)
— *end note*]
#### [13.5.2.2](#op) Logical operations [[temp.constr.op]](temp.constr.op)
[1](#op-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640)
There are two binary logical operations on constraints: conjunction
and disjunction[.](#op-1.sentence-1)
[*Note [1](#op-note-1)*:
These logical operations have no corresponding C++ syntax[.](#op-1.sentence-2)
For the purpose of exposition, conjunction is spelled
using the symbol ∧ and disjunction is spelled using the
symbol ∨ [.](#op-1.sentence-3)
The operands of these operations are called the left
and right operands[.](#op-1.sentence-4)
In the constraint A ∧ B,A is the left operand, and B is the right operand[.](#op-1.sentence-5)
— *end note*]
[2](#op-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653)
A [*conjunction*](#def:conjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#op-2.sentence-1)
To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#op-2.sentence-2)
If that is not satisfied, the conjunction is not satisfied[.](#op-2.sentence-3)
Otherwise, the conjunction is satisfied if and only if the second
operand is satisfied[.](#op-2.sentence-4)
[3](#op-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664)
A [*disjunction*](#def:disjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#op-3.sentence-1)
To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#op-3.sentence-2)
If that is satisfied, the disjunction is satisfied[.](#op-3.sentence-3)
Otherwise, the disjunction is satisfied if and only if the second
operand is satisfied[.](#op-3.sentence-4)
[4](#op-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676)
[*Example [1](#op-example-1)*: template<typename T>constexpr bool get_value() { return T::value; }template<typename T>requires (sizeof(T) > 1) && (get_value<T>())void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value<T>()void f(int);
f('a'); // OK, calls f(int)
In the satisfaction of the [associated constraints](#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied;
the second operand is not checked for satisfaction[.](#op-4.sentence-1)
— *end example*]
[5](#op-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695)
[*Note [2](#op-note-2)*:
A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")) is an atomic constraint;
the negation operator is not treated as a logical operation on constraints[.](#op-5.sentence-1)
As a result, distinct negation [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading") do not subsume one another under [[temp.constr.order]](#order "13.5.5Partial ordering by constraints")[.](#op-5.sentence-2)
Furthermore, if substitution to determine
whether an atomic constraint is satisfied ([[temp.constr.atomic]](#atomic "13.5.2.3Atomic constraints"))
encounters a substitution failure, the constraint is not satisfied,
regardless of the presence of a negation operator[.](#op-5.sentence-3)
[*Example [2](#op-example-2)*: template <class T> concept sad = false;
template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([[temp.constr.atomic]](#atomic "13.5.2.3Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sadtemplate <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
Here,requires (!sad<typename T::type>) requires
that there is a nested type that is not sad,
whereasrequires (!sad_nested_type<T>) requires
that there is no sad nested type[.](#op-5.sentence-4)
— *end example*]
— *end note*]
#### [13.5.2.3](#atomic) Atomic constraints [[temp.constr.atomic]](temp.constr.atomic)
[1](#atomic-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738)
An [*atomic constraint*](#def:constraint,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]") is formed from
an expression E and a mapping from the template parameters
that appear within E to
template arguments that are formed via substitution during constraint normalization
in the declaration of a constrained entity (and, therefore, can involve the
unsubstituted template parameters of the constrained entity),
called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3Atomic constraints[temp.constr.atomic]") ([[temp.constr.decl]](#decl "13.5.3Constrained declarations"))[.](#atomic-1.sentence-1)
[*Note [1](#atomic-note-1)*:
Atomic constraints are formed by [constraint normalization](#def:constraint,normalization "13.5.4Constraint normalization[temp.constr.normal]")[.](#atomic-1.sentence-2)
E is never a [logical and expression](expr.log.and "7.6.14Logical AND operator[expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15Logical OR operator[expr.log.or]")[.](#atomic-1.sentence-3)
— *end note*]
[2](#atomic-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753)
Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3Atomic constraints[temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) to
those mapped by the parameter mappings of the expression,
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6Type equivalence")) as
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e2[.](#atomic-2.sentence-1)
[*Note [2](#atomic-note-2)*:
The comparison of parameter mappings of atomic constraints
operates in a manner similar to that of declaration matching
with alias template substitution ([[temp.alias]](temp.alias "13.7.8Alias templates"))[.](#atomic-2.sentence-2)
[*Example [1](#atomic-example-1)*: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f()requires Add1<2 * M>;template <unsigned M> int f()requires AddOne<2 * M> && true;
int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>// with mapping similar to N↦2 * M + 1template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);
void h() { g<0>(nullptr); // OK, there is only one g} — *end example*]
As specified in [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"),
if the validity or meaning of the program depends on
whether two constructs are equivalent, and
they are functionally equivalent but not equivalent,
the program is ill-formed, no diagnostic required[.](#atomic-2.sentence-3)
[*Example [2](#atomic-example-2)*: template <unsigned N> void f2()requires Add1<2 * N>;template <unsigned N> int f2()requires Add1<N * 2> && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} — *end example*]
— *end note*]
[3](#atomic-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819)
To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]"),
the parameter mapping and template arguments are
first substituted into its expression[.](#atomic-3.sentence-1)
If substitution results in an invalid type or expression
in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#atomic-3.sentence-2)
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]") is performed if necessary,
and E shall be a constant expression of type bool[.](#atomic-3.sentence-3)
The constraint is satisfied if and only if evaluation of E results in true[.](#atomic-3.sentence-4)
If, at different points in the program, the satisfaction result is different
for identical atomic constraints and template arguments,
the program is ill-formed, no diagnostic required[.](#atomic-3.sentence-5)
[*Example [3](#atomic-example-3)*: template<typename T> concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate<typename T> struct S {constexpr operator bool() const { return true; }};
template<typename T> requires (S<T>{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S<int>{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match — *end example*]
#### [13.5.2.4](#concept) Concept-dependent constraints [[temp.constr.concept]](temp.constr.concept)
[1](#concept-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857)
A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]") CD is
an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") names a dependent concept named C[.](#concept-1.sentence-1)
[2](#concept-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862)
To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]"),
the parameter mapping and template arguments are first
substituted into C[.](#concept-2.sentence-1)
If substitution results in an invalid concept-id in
the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#concept-2.sentence-2)
Otherwise, let CI′ be
the normal form ([[temp.constr.normal]](#normal "13.5.4Constraint normalization")) of the concept-id
after substitution of C[.](#concept-2.sentence-3)
[*Note [1](#concept-note-1)*:
Normalization of CI might be ill-formed; no diagnostics is required[.](#concept-2.sentence-4)
— *end note*]
[3](#concept-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877)
To form CI′′,
each appearance of C's template parameters in
the parameter mappings of the atomic constraints
(including concept-dependent constraints)
in CI′ is substituted with their respective arguments from
the parameter mapping of CD and the arguments of CI[.](#concept-3.sentence-1)
[4](#concept-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886)
CD is satisfied if CI′′ is satisfied[.](#concept-4.sentence-1)
[*Note [2](#concept-note-2)*:
Checking whether CI′′ is satisfied
can lead to further normalization of concept-dependent constraints[.](#concept-4.sentence-2)
— *end note*]
[*Example [1](#concept-example-1)*: template<typename>concept C = true;
template<typename T, template<typename> concept CC>concept D = CC<T>;
template<typename U, template<typename> concept CT, template<typename, template<typename> concept> concept CU>int f() requires CU<U, CT>;int i = f<int, C, D>();
In this example, the associated constraints of f consist of a concept-dependent constraint
whose expression is the concept-id CU<U, CT> with the mappingU↦U,CT↦CT,CU↦CU[.](#concept-4.sentence-3)
The result of substituting D into this expression is D<U, CT>[.](#concept-4.sentence-4)
We consider the normal form of the resulting concept-id,
which is CC<T> with the mappingT↦U,CC↦CT[.](#concept-4.sentence-5)
By recursion, C is substituted into CC<T>, and the result
is normalized to the atomic constraint true, which is satisfied[.](#concept-4.sentence-6)
— *end example*]
#### [13.5.2.5](#fold) Fold expanded constraint [[temp.constr.fold]](temp.constr.fold)
[1](#fold-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920)
A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5Fold expanded constraint[temp.constr.fold]") is formed from a constraint C and
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") which can either be && or ||[.](#fold-1.sentence-1)
A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#fold-1.sentence-2)
Let N be the number of elements
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#fold-1.sentence-3)
[2](#fold-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is && is satisfied if it is a valid pack expansion and
if N=0 or if for each i where 0≤i<N in increasing order,C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#fold-2.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is not satisfied[.](#fold-2.sentence-2)
[3](#fold-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1938)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is || is satisfied if it is a valid pack expansion,N>0, and if for i where 0≤i<N in increasing order,
there is a smallest i for which C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#fold-3.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is satisfied[.](#fold-3.sentence-2)
[4](#fold-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1948)
[*Note [1](#fold-note-1)*:
If the pack expansion expands packs of different size,
then it is invalid and the fold expanded constraint is not satisfied[.](#fold-4.sentence-1)
— *end note*]
[5](#fold-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1954)
Two fold expanded constraints are [*compatible for subsumption*](#def:subsumption,compatible_for "13.5.2.5Fold expanded constraint[temp.constr.fold]") if their respective constraints both contain
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#fold-5.sentence-1)
### [13.5.3](#decl) Constrained declarations [[temp.constr.decl]](temp.constr.decl)
[1](#decl-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1961)
A template declaration ([[temp.pre]](temp.pre "13.1Preamble"))
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")[.](#decl-1.sentence-1)
This allows the specification of constraints for that declaration as
an expression:
[constraint-expression:](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]")
[2](#decl-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1972)
Constraints can also be associated with a declaration through the use of[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") or parameter-type-list[.](#decl-2.sentence-1)
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* that are used to constrain the declaration[.](#decl-2.sentence-2)
[3](#decl-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1979)
A declaration's [*associated constraints*](#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") are defined as follows:
- [(3.1)](#decl-3.1)
If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s*,
the declaration has no associated constraints[.](#decl-3.1.sentence-1)
- [(3.2)](#decl-3.2)
Otherwise, if there is a single introduced [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]"),
the associated constraints are the [normal form](#def:normal_form,constraint "13.5.4Constraint normalization[temp.constr.normal]") of that expression[.](#decl-3.2.sentence-1)
- [(3.3)](#decl-3.3)
Otherwise, the associated constraints are the normal form of a [logicaland expression](expr.log.and "7.6.14Logical AND operator[expr.log.and]") whose operands are in the
following order:
* [(3.3.1)](#decl-3.3.1)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")) in
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"),
in order of appearance, and
* [(3.3.2)](#decl-3.3.2)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") following
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")), and
* [(3.3.3)](#decl-3.3.3)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") in
the parameter-type-list of a function declaration, and
* [(3.3.4)](#decl-3.3.4)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators")) of
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#decl-3.3.sentence-1)
The formation of the associated constraints
establishes the order in which constraints are instantiated when checking
for satisfaction ([[temp.constr.constr]](#constr "13.5.2Constraints"))[.](#decl-3.sentence-2)
[*Example [1](#decl-example-1)*: template<typename T> concept C = true;
template<C T> void f1(T);template<typename T> requires C<T> void f2(T);template<typename T> void f3(T) requires C<T>;
The functions f1, f2, and f3 have the associated
constraint C<T>[.](#decl-3.sentence-3)
template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) > 0;
template<C1 T> void f4(T) requires C2<T>;template<typename T> requires C1<T> && C2<T> void f5(T);
The associated constraints of f4 and f5 are C1<T> ∧ C2<T>[.](#decl-3.sentence-4)
template<C1 T> requires C2<T> void f6();template<C2 T> requires C1<T> void f7();
The associated constraints off6 are C1<T> ∧ C2<T>,
and those off7 are C2<T> ∧ C1<T>[.](#decl-3.sentence-5)
— *end example*]
[4](#decl-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2051)
When determining whether a given introduced[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") C1 of a declaration
in an instantiated specialization of a templated class
is equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") C2 of a declaration
outside the class body,C1 is instantiated[.](#decl-4.sentence-1)
If the instantiation results in an invalid expression,
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* are not equivalent[.](#decl-4.sentence-2)
[*Note [1](#decl-note-1)*:
This can happen when determining which member template is specialized
by an explicit specialization declaration[.](#decl-4.sentence-3)
— *end note*]
[*Example [2](#decl-example-2)*: template <class T> concept C = true;template <class T> struct A {template <class U> U f(U) requires C<typename T::type>; // #1template <class U> U f(U) requires C<T>; // #2};
template <> template <class U> U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
Substituting int for T in C<typename T::type> produces an invalid expression, so the specialization does not match #1[.](#decl-4.sentence-4)
Substituting int for T in C<T> produces C<int>,
which is equivalent to the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") for the specialization,
so it does match #2[.](#decl-4.sentence-5)
— *end example*]
### [13.5.4](#normal) Constraint normalization [[temp.constr.normal]](temp.constr.normal)
[1](#normal-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2085)
The [*normal form*](#def:normal_form,constraint "13.5.4Constraint normalization[temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") E is
a [constraint](#def:constraint "13.5.2Constraints[temp.constr.constr]") that is defined as follows:
- [(1.1)](#normal-1.1)
The normal form of an expression ( E ) is
the normal form of E[.](#normal-1.1.sentence-1)
- [(1.2)](#normal-1.2)
The normal form of an expression E1 || E2 is
the [disjunction](#def:disjunction "13.5.2.2Logical operations[temp.constr.op]") of
the normal forms of E1 and E2[.](#normal-1.2.sentence-1)
- [(1.3)](#normal-1.3)
The normal form of an expression E1 && E2 is the conjunction of
the normal forms of E1 and E2[.](#normal-1.3.sentence-1)
- [(1.4)](#normal-1.4)
For a concept-id C<A1, A2, …, An> termed CI:
* [(1.4.1)](#normal-1.4.1)
If C names a dependent concept,
the normal form of CI is a concept-dependent constraint
whose concept-id is CI and
whose parameter mapping is the identity mapping[.](#normal-1.4.1.sentence-1)
* [(1.4.2)](#normal-1.4.2)
Otherwise, to form CE,
any non-dependent concept template argument Ai is substituted into the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") of C[.](#normal-1.4.2.sentence-1)
If any such substitution results in an invalid concept-id,
the program is ill-formed; no diagnostic is required[.](#normal-1.4.2.sentence-2)
The normal form of CI is the result of substituting,
in the normal form N of CE,
appearances of C's template parameters
in the parameter mappings of the atomic constraints in N with their respective arguments from C[.](#normal-1.4.2.sentence-3)
If any such substitution results in an invalid type or expression,
the program is ill-formed; no diagnostic is required[.](#normal-1.4.2.sentence-4)
[*Example [1](#normal-example-1)*: template<typename T> concept A = T::value || true;template<typename U> concept B = A<U*>;template<typename V> concept C = B<V&>;
Normalization of B's [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is valid and results inT::value (with the mapping T↦U*) ∨ true (with an empty mapping),
despite the expression T::value being ill-formed
for a pointer type T[.](#normal-1.4.sentence-2)
Normalization of C's [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") results in the program being ill-formed,
because it would form the invalid type V&* in the parameter mapping[.](#normal-1.4.sentence-3)
— *end example*]
- [(1.5)](#normal-1.5)
For a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7Fold expressions"))
that is either && or ||:
* [(1.5.1)](#normal-1.5.1)
The normal form of an expression ( ... Op E ) is the normal form of ( E Op ... )[.](#normal-1.5.1.sentence-1)
* [(1.5.2)](#normal-1.5.2)
The normal form of an expression ( E1 Op ... Op E2 ) is the normal form of
+
[(1.5.2.1)](#normal-1.5.2.1)
( E1 Op ... ) Op E2 if E1 contains an unexpanded pack, or
+
[(1.5.2.2)](#normal-1.5.2.2)
E1 Op ( E2 Op ... ) otherwise[.](#normal-1.5.2.sentence-1)
* [(1.5.3)](#normal-1.5.3)
The normal form of an expression F of the form ( E Op ... ) is as follows:
If E contains an unexpanded concept template parameter pack,
it shall not contain an unexpanded template parameter pack of another kind[.](#normal-1.5.3.sentence-2)
Let E′ be the normal form of E[.](#normal-1.5.3.sentence-3)
+
[(1.5.3.1)](#normal-1.5.3.1)
If E contains
an unexpanded concept template parameter pack Pk that
has corresponding template arguments in
the parameter mapping of any atomic constraint
(including concept-dependent constraints) of E′,
the number of arguments specified for all such Pk shall be the same number N[.](#normal-1.5.3.1.sentence-1)
The normal form of F is the normal form of E0 Op Op EN−1 after substituting in Ei the respective ith concept argument of each Pk[.](#normal-1.5.3.1.sentence-2)
If any such substitution results in an invalid type or expression,
the program is ill-formed; no diagnostic is required[.](#normal-1.5.3.1.sentence-3)
+
[(1.5.3.2)](#normal-1.5.3.2)
Otherwise,
the normal form of F is
a fold expanded constraint ([[temp.constr.fold]](#fold "13.5.2.5Fold expanded constraint")) whose
constraint is E′ and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is Op[.](#normal-1.5.3.2.sentence-1)
- [(1.6)](#normal-1.6)
The normal form of any other expression E is
the atomic constraint
whose expression is E and
whose parameter mapping is the identity mapping[.](#normal-1.6.sentence-1)
[2](#normal-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2201)
The process of obtaining the normal form of a[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4Constraint normalization[temp.constr.normal]")[.](#normal-2.sentence-1)
[*Note [1](#normal-note-1)*:
Normalization of [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* is performed
when determining the associated constraints ([[temp.constr.constr]](#constr "13.5.2Constraints"))
of a declaration
and
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5Names"))[.](#normal-2.sentence-2)
— *end note*]
[3](#normal-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2217)
[*Example [2](#normal-example-2)*: template<typename T> concept C1 = sizeof(T) == 1;template<typename T> concept C2 = C1<T> && 1 == 2;template<typename T> concept C3 = requires { typename T::type; };template<typename T> concept C4 = requires (T x) { ++x; };
template<C2 U> void f1(U); // #1template<C3 U> void f2(U); // #2template<C4 U> void f3(U); // #3
The associated constraints of #1 aresizeof(T) == 1 (with mapping T↦U) ∧ 1 == 2[.](#normal-3.sentence-1)
The associated constraints of #2 arerequires { typename T::type; } (with mapping T↦U)[.](#normal-3.sentence-2)
The associated constraints of #3 arerequires (T x) { ++x; } (with mapping T↦U)[.](#normal-3.sentence-3)
— *end example*]
[*Example [3](#normal-example-3)*: template<typename T>concept C = true;template<typename T, template<typename> concept CT>concept CC = CT<T>;
template<typename U, template<typename, template<typename> concept> concept CT>void f() requires CT<U*, C>;template<typename U>void g() requires CC<U*, C>;
The normal form of the associated constraints of f is
the concept-dependent constraint CT<T, C>[.](#normal-3.sentence-4)
The normal form of the associated constraints of g is
the atomic constraint true[.](#normal-3.sentence-5)
— *end example*]
[*Example [4](#normal-example-4)*: template<typename T>concept A = true;template<typename T>concept B = A<T> && true; // B subsumes Atemplate<typename T>concept C = true;template<typename T>concept D = C<T> && true; // D subsumes Ctemplate<typename T, template<typename> concept... CTs>concept all_of = (CTs<T> && ...);
template<typename T> requires all_of<T, A, C>constexpr int f(T) { return 1; } // #1template<typename T> requires all_of<T, B, D>constexpr int f(T) { return 2; } // #2static_assert(f(1) == 2); // ok
The normal form of all_of<T, A, C> is
the conjunction of the normal forms of A<T> and C<T>[.](#normal-3.sentence-6)
Similarly, the normal form of all_of<T, B, D> is
the conjunction of the normal forms of B<T> and D<T>[.](#normal-3.sentence-7)
#2 therefore is more constrained than #1[.](#normal-3.sentence-8)
— *end example*]
[*Example [5](#normal-example-5)*: template<typename T, template<typename> concept>struct wrapper {};
template<typename... T, template<typename> concept... CTs>int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains// different kinds of template parameters — *end example*]
### [13.5.5](#order) Partial ordering by constraints [[temp.constr.order]](temp.constr.order)
[1](#order-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2299)
A constraint P [*subsumes*](#def:constraint,subsumption "13.5.5Partial ordering by constraints[temp.constr.order]") a constraint Q if and only if,
for every disjunctive clause Pi in the disjunctive normal form[110](#footnote-110 "A constraint is in disjunctive normal form when it is a disjunction of clauses where each clause is a conjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the disjunctive normal form of the constraint A  ∧ (B ∨C) is (A ∧B)  ∨ (A ∧C). Its disjunctive clauses are (A ∧B) and (A ∧C).") of P, Pi subsumes every conjunctive clause Qj in the conjunctive normal form[111](#footnote-111 "A constraint is in conjunctive normal form when it is a conjunction of clauses where each clause is a disjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the constraint A  ∧ (B ∨C) is in conjunctive normal form. Its conjunctive clauses are A and (B ∨C).") of Q, where
- [(1.1)](#order-1.1)
a disjunctive clause Pi subsumes a conjunctive clause Qj if and only
if there exists an atomic constraint Pia in Pi for which there exists
an atomic constraint Qjb in Qj such that Pia subsumes Qjb,
- [(1.2)](#order-1.2)
an atomic constraint A subsumes another atomic constraintB if and only if A and B are identical using the
rules described in [[temp.constr.atomic]](#atomic "13.5.2.3Atomic constraints"), and
- [(1.3)](#order-1.3)
a fold expanded constraint A subsumes
another fold expanded constraint B if they are compatible for subsumption,
have the same [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]"), and
the constraint of A subsumes that of B[.](#order-1.sentence-1)
[*Example [1](#order-example-1)*:
Let A and B be [atomic constraints](#def:constraint,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]")[.](#order-1.sentence-2)
The constraint A ∧ B subsumes A, but A does not subsume A ∧ B[.](#order-1.sentence-3)
The constraint A subsumes A ∨ B, but A ∨ B does not subsume A[.](#order-1.sentence-4)
Also note that every constraint subsumes itself[.](#order-1.sentence-5)
— *end example*]
[2](#order-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2354)
[*Note [1](#order-note-1)*:
The subsumption relation defines a partial ordering on constraints[.](#order-2.sentence-1)
This partial ordering is used to determine
- [(2.1)](#order-2.1)
the best viable candidate of non-template functions ([[over.match.best]](over.match.best "12.2.4Best viable function")),
- [(2.2)](#order-2.2)
the address of a non-template function ([[over.over]](over.over "12.3Address of an overload set")),
- [(2.3)](#order-2.3)
the matching of template template arguments ([[temp.arg.template]](temp.arg.template "13.4.4Template template arguments")),
- [(2.4)](#order-2.4)
the partial ordering of class template specializations ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3Partial ordering of partial specializations")), and
- [(2.5)](#order-2.5)
the partial ordering of function templates ([[temp.func.order]](temp.func.order "13.7.7.3Partial ordering of function templates"))[.](#order-2.sentence-2)
— *end note*]
[3](#order-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2367)
The associated constraints C of a declaration Dare [*eligible for subsumption*](#def:eligible,for_subsumption "13.5.5Partial ordering by constraints[temp.constr.order]") unless C contains a concept-dependent constraint[.](#order-3.sentence-1)
[4](#order-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2378)
A declaration D1 is[*at least as constrained*](#def:at_least_as_constrained "13.5.5Partial ordering by constraints[temp.constr.order]") as
a declaration D2 if
- [(4.1)](#order-4.1)
D1 and D2 are both constrained declarations andD1's associated constraints
are eligible for subsumption and subsume those of D2; or
- [(4.2)](#order-4.2)
D2 has no associated constraints[.](#order-4.sentence-1)
[5](#order-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2390)
A declaration D1 is [*more constrained*](#def:more_constrained "13.5.5Partial ordering by constraints[temp.constr.order]") than another declaration D2 when D1 is at least as
constrained as D2, and D2 is not at least as
constrained as D1[.](#order-5.sentence-1)
[*Example [2](#order-example-2)*: template<typename T> concept C1 = requires(T t) { --t; };template<typename T> concept C2 = C1<T> && requires(T t) { *t; };
template<C1 T> void f(T); // #1template<C2 T> void f(T); // #2template<typename T> void g(T); // #3template<C1 T> void g(T); // #4 f(0); // selects #1 f((int*)0); // selects #2 g(true); // selects #3 because C1<bool> is not satisfied g(0); // selects #4 — *end example*]
[*Example [3](#order-example-3)*: template<template<typename T> concept CT, typename T>struct S {};template<typename T>concept A = true;
template<template<typename T> concept X, typename T>int f(S<X, T>) requires A<T> { return 42; } // #1template<template<typename T> concept X, typename T>int f(S<X, T>) requires X<T> { return 43; } // #2 f(S<A, int>{}); // ok, select #1 because #2 is not eligible for subsumption — *end example*]
[6](#order-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2427)
A non-template function F1 is [*more partial-ordering-constrained*](#def:more_partial-ordering-constrained "13.5.5Partial ordering by constraints[temp.constr.order]") than a non-template function F2 if
- [(6.1)](#order-6.1)
they have the same non-object-parameter-type-lists ([[dcl.fct]](dcl.fct "9.3.4.6Functions")), and
- [(6.2)](#order-6.2)
if they are member functions, both are direct members of the same class, and
- [(6.3)](#order-6.3)
if both are non-static member functions,
they have the same types for their object parameters, and
- [(6.4)](#order-6.4)
the declaration of F1 is more constrained than
the declaration of F2[.](#order-6.sentence-1)
[110)](#footnote-110)[110)](#footnoteref-110)
A constraint is in disjunctive normal form when it is a disjunction of
clauses where each clause is a conjunction of fold expanded or atomic constraints[.](#footnote-110.sentence-1)
For atomic constraints A, B, and C, the disjunctive normal form
of the constraintA ∧ (B ∨ C) is(A ∧ B) ∨ (A ∧ C)[.](#footnote-110.sentence-2)
Its disjunctive clauses are (A ∧ B) and (A ∧ C)[.](#footnote-110.sentence-3)
[111)](#footnote-111)[111)](#footnoteref-111)
A constraint is in conjunctive normal form when it is a conjunction
of clauses where each clause is a disjunction of fold expanded or atomic constraints[.](#footnote-111.sentence-1)
For atomic constraints A, B, and C, the constraintA ∧ (B ∨ C) is in conjunctive normal form[.](#footnote-111.sentence-2)
Its conjunctive clauses are A and (B ∨ C)[.](#footnote-111.sentence-3)

View File

@@ -0,0 +1,87 @@
[temp.constr.atomic]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#atomic)
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.atomic)
#### 13.5.2.3 Atomic constraints [temp.constr.atomic]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738)
An [*atomic constraint*](#def:constraint,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]") is formed from
an expression E and a mapping from the template parameters
that appear within E to
template arguments that are formed via substitution during constraint normalization
in the declaration of a constrained entity (and, therefore, can involve the
unsubstituted template parameters of the constrained entity),
called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3Atomic constraints[temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4Constraint normalization[temp.constr.normal]")[.](#1.sentence-2)
E is never a [logical and expression](expr.log.and "7.6.14Logical AND operator[expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15Logical OR operator[expr.log.or]")[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753)
Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3Atomic constraints[temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) to
those mapped by the parameter mappings of the expression,
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6Type equivalence")) as
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e2[.](#2.sentence-1)
[*Note [2](#note-2)*:
The comparison of parameter mappings of atomic constraints
operates in a manner similar to that of declaration matching
with alias template substitution ([[temp.alias]](temp.alias "13.7.8Alias templates"))[.](#2.sentence-2)
[*Example [1](#example-1)*: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f()requires Add1<2 * M>;template <unsigned M> int f()requires AddOne<2 * M> && true;
int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>// with mapping similar to N↦2 * M + 1template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);
void h() { g<0>(nullptr); // OK, there is only one g} — *end example*]
As specified in [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"),
if the validity or meaning of the program depends on
whether two constructs are equivalent, and
they are functionally equivalent but not equivalent,
the program is ill-formed, no diagnostic required[.](#2.sentence-3)
[*Example [2](#example-2)*: template <unsigned N> void f2()requires Add1<2 * N>;template <unsigned N> int f2()requires Add1<N * 2> && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} — *end example*]
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819)
To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]"),
the parameter mapping and template arguments are
first substituted into its expression[.](#3.sentence-1)
If substitution results in an invalid type or expression
in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#3.sentence-2)
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]") is performed if necessary,
and E shall be a constant expression of type bool[.](#3.sentence-3)
The constraint is satisfied if and only if evaluation of E results in true[.](#3.sentence-4)
If, at different points in the program, the satisfaction result is different
for identical atomic constraints and template arguments,
the program is ill-formed, no diagnostic required[.](#3.sentence-5)
[*Example [3](#example-3)*: template<typename T> concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate<typename T> struct S {constexpr operator bool() const { return true; }};
template<typename T> requires (S<T>{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S<int>{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match — *end example*]

View File

@@ -0,0 +1,81 @@
[temp.constr.concept]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#concept)
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.concept)
#### 13.5.2.4 Concept-dependent constraints [temp.constr.concept]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857)
A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]") CD is
an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") names a dependent concept named C[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862)
To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]"),
the parameter mapping and template arguments are first
substituted into C[.](#2.sentence-1)
If substitution results in an invalid concept-id in
the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#2.sentence-2)
Otherwise, let CI′ be
the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4Constraint normalization")) of the concept-id
after substitution of C[.](#2.sentence-3)
[*Note [1](#note-1)*:
Normalization of CI might be ill-formed; no diagnostics is required[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877)
To form CI′′,
each appearance of C's template parameters in
the parameter mappings of the atomic constraints
(including concept-dependent constraints)
in CI′ is substituted with their respective arguments from
the parameter mapping of CD and the arguments of CI[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886)
CD is satisfied if CI′′ is satisfied[.](#4.sentence-1)
[*Note [2](#note-2)*:
Checking whether CI′′ is satisfied
can lead to further normalization of concept-dependent constraints[.](#4.sentence-2)
— *end note*]
[*Example [1](#example-1)*: template<typename>concept C = true;
template<typename T, template<typename> concept CC>concept D = CC<T>;
template<typename U, template<typename> concept CT, template<typename, template<typename> concept> concept CU>int f() requires CU<U, CT>;int i = f<int, C, D>();
In this example, the associated constraints of f consist of a concept-dependent constraint
whose expression is the concept-id CU<U, CT> with the mappingU↦U,CT↦CT,CU↦CU[.](#4.sentence-3)
The result of substituting D into this expression is D<U, CT>[.](#4.sentence-4)
We consider the normal form of the resulting concept-id,
which is CC<T> with the mappingT↦U,CC↦CT[.](#4.sentence-5)
By recursion, C is substituted into CC<T>, and the result
is normalized to the atomic constraint true, which is satisfied[.](#4.sentence-6)
— *end example*]

View File

@@ -0,0 +1,368 @@
[temp.constr.constr]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#constr)
### 13.5.2 Constraints [temp.constr.constr]
#### [13.5.2.1](#general) General [[temp.constr.constr.general]](temp.constr.constr.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610)
A [*constraint*](#def:constraint "13.5.2.1General[temp.constr.constr.general]") is a sequence of logical operations and
operands that specifies requirements on template arguments[.](#general-1.sentence-1)
The operands of a logical operation are constraints[.](#general-1.sentence-2)
There are five different kinds of constraints:
- [(1.1)](#general-1.1)
conjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2Logical operations")),
- [(1.2)](#general-1.2)
disjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2Logical operations")),
- [(1.3)](#general-1.3)
atomic constraints ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3Atomic constraints")),
- [(1.4)](#general-1.4)
concept-dependent constraints ([[temp.constr.concept]](#temp.constr.concept "13.5.2.4Concept-dependent constraints")), and
- [(1.5)](#general-1.5)
fold expanded constraints ([[temp.constr.fold]](#temp.constr.fold "13.5.2.5Fold expanded constraint"))[.](#general-1.sentence-3)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623)
In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9Template instantiation and specialization")),
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#general-2.sentence-1)
[*Note [1](#general-note-1)*:
Forming the name of a specialization of
a class template,
a variable template, or
an alias template ([[temp.names]](temp.names "13.3Names of template specializations"))
requires the satisfaction of its constraints[.](#general-2.sentence-2)
[Overload resolution](over.match.viable "12.2.3Viable functions[over.match.viable]") requires the satisfaction of constraints
on functions and function templates[.](#general-2.sentence-3)
— *end note*]
#### [13.5.2.2](#temp.constr.op) Logical operations [[temp.constr.op]](temp.constr.op)
[1](#temp.constr.op-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640)
There are two binary logical operations on constraints: conjunction
and disjunction[.](#temp.constr.op-1.sentence-1)
[*Note [1](#temp.constr.op-note-1)*:
These logical operations have no corresponding C++ syntax[.](#temp.constr.op-1.sentence-2)
For the purpose of exposition, conjunction is spelled
using the symbol ∧ and disjunction is spelled using the
symbol ∨ [.](#temp.constr.op-1.sentence-3)
The operands of these operations are called the left
and right operands[.](#temp.constr.op-1.sentence-4)
In the constraint A ∧ B,A is the left operand, and B is the right operand[.](#temp.constr.op-1.sentence-5)
— *end note*]
[2](#temp.constr.op-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653)
A [*conjunction*](#def:conjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#temp.constr.op-2.sentence-1)
To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#temp.constr.op-2.sentence-2)
If that is not satisfied, the conjunction is not satisfied[.](#temp.constr.op-2.sentence-3)
Otherwise, the conjunction is satisfied if and only if the second
operand is satisfied[.](#temp.constr.op-2.sentence-4)
[3](#temp.constr.op-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664)
A [*disjunction*](#def:disjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#temp.constr.op-3.sentence-1)
To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#temp.constr.op-3.sentence-2)
If that is satisfied, the disjunction is satisfied[.](#temp.constr.op-3.sentence-3)
Otherwise, the disjunction is satisfied if and only if the second
operand is satisfied[.](#temp.constr.op-3.sentence-4)
[4](#temp.constr.op-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676)
[*Example [1](#temp.constr.op-example-1)*: template<typename T>constexpr bool get_value() { return T::value; }template<typename T>requires (sizeof(T) > 1) && (get_value<T>())void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value<T>()void f(int);
f('a'); // OK, calls f(int)
In the satisfaction of the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied;
the second operand is not checked for satisfaction[.](#temp.constr.op-4.sentence-1)
— *end example*]
[5](#temp.constr.op-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695)
[*Note [2](#temp.constr.op-note-2)*:
A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")) is an atomic constraint;
the negation operator is not treated as a logical operation on constraints[.](#temp.constr.op-5.sentence-1)
As a result, distinct negation [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints")[.](#temp.constr.op-5.sentence-2)
Furthermore, if substitution to determine
whether an atomic constraint is satisfied ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3Atomic constraints"))
encounters a substitution failure, the constraint is not satisfied,
regardless of the presence of a negation operator[.](#temp.constr.op-5.sentence-3)
[*Example [2](#temp.constr.op-example-2)*: template <class T> concept sad = false;
template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sadtemplate <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
Here,requires (!sad<typename T::type>) requires
that there is a nested type that is not sad,
whereasrequires (!sad_nested_type<T>) requires
that there is no sad nested type[.](#temp.constr.op-5.sentence-4)
— *end example*]
— *end note*]
#### [13.5.2.3](#temp.constr.atomic) Atomic constraints [[temp.constr.atomic]](temp.constr.atomic)
[1](#temp.constr.atomic-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1738)
An [*atomic constraint*](#def:constraint,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]") is formed from
an expression E and a mapping from the template parameters
that appear within E to
template arguments that are formed via substitution during constraint normalization
in the declaration of a constrained entity (and, therefore, can involve the
unsubstituted template parameters of the constrained entity),
called the [*parameter mapping*](#def:parameter_mapping "13.5.2.3Atomic constraints[temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))[.](#temp.constr.atomic-1.sentence-1)
[*Note [1](#temp.constr.atomic-note-1)*:
Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4Constraint normalization[temp.constr.normal]")[.](#temp.constr.atomic-1.sentence-2)
E is never a [logical and expression](expr.log.and "7.6.14Logical AND operator[expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15Logical OR operator[expr.log.or]")[.](#temp.constr.atomic-1.sentence-3)
— *end note*]
[2](#temp.constr.atomic-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1753)
Two atomic constraints, e1 and e2, are[*identical*](#def:atomic_constraint,identical "13.5.2.3Atomic constraints[temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) to
those mapped by the parameter mappings of the expression,
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6Type equivalence")) as
a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are
the targets of the parameter mapping of e2[.](#temp.constr.atomic-2.sentence-1)
[*Note [2](#temp.constr.atomic-note-2)*:
The comparison of parameter mappings of atomic constraints
operates in a manner similar to that of declaration matching
with alias template substitution ([[temp.alias]](temp.alias "13.7.8Alias templates"))[.](#temp.constr.atomic-2.sentence-2)
[*Example [1](#temp.constr.atomic-example-1)*: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f()requires Add1<2 * M>;template <unsigned M> int f()requires AddOne<2 * M> && true;
int x = f<0>(); // OK, the atomic constraints from concept C in both fs are Atomic<N>// with mapping similar to N↦2 * M + 1template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);
void h() { g<0>(nullptr); // OK, there is only one g} — *end example*]
As specified in [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"),
if the validity or meaning of the program depends on
whether two constructs are equivalent, and
they are functionally equivalent but not equivalent,
the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-2.sentence-3)
[*Example [2](#temp.constr.atomic-example-2)*: template <unsigned N> void f2()requires Add1<2 * N>;template <unsigned N> int f2()requires Add1<N * 2> && true;void h2() { f2<0>(); // ill-formed, no diagnostic required:// requires determination of subsumption between atomic constraints that are// functionally equivalent but not equivalent} — *end example*]
— *end note*]
[3](#temp.constr.atomic-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1819)
To determine if an atomic constraint is[*satisfied*](#def:constraint,satisfaction,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]"),
the parameter mapping and template arguments are
first substituted into its expression[.](#temp.constr.atomic-3.sentence-1)
If substitution results in an invalid type or expression
in the immediate context of the atomic constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#temp.constr.atomic-3.sentence-2)
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]") is performed if necessary,
and E shall be a constant expression of type bool[.](#temp.constr.atomic-3.sentence-3)
The constraint is satisfied if and only if evaluation of E results in true[.](#temp.constr.atomic-3.sentence-4)
If, at different points in the program, the satisfaction result is different
for identical atomic constraints and template arguments,
the program is ill-formed, no diagnostic required[.](#temp.constr.atomic-3.sentence-5)
[*Example [3](#temp.constr.atomic-example-3)*: template<typename T> concept C =sizeof(T) == 4 && !true; // requires atomic constraints sizeof(T) == 4 and !truetemplate<typename T> struct S {constexpr operator bool() const { return true; }};
template<typename T> requires (S<T>{})void f(T); // #1void f(int); // #2void g() { f(0); // error: expression S<int>{} does not have type bool} // while checking satisfaction of deduced arguments of #1;// call is ill-formed even though #2 is a better match — *end example*]
#### [13.5.2.4](#temp.constr.concept) Concept-dependent constraints [[temp.constr.concept]](temp.constr.concept)
[1](#temp.constr.concept-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1857)
A [*concept-dependent constraint*](#def:constraint,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]") CD is
an atomic constraint whose expression is a concept-id CI whose[*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") names a dependent concept named C[.](#temp.constr.concept-1.sentence-1)
[2](#temp.constr.concept-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1862)
To determine if CD is[*satisfied*](#def:constraint,satisfaction,concept-dependent "13.5.2.4Concept-dependent constraints[temp.constr.concept]"),
the parameter mapping and template arguments are first
substituted into C[.](#temp.constr.concept-2.sentence-1)
If substitution results in an invalid concept-id in
the immediate context of the constraint ([[temp.deduct.general]](temp.deduct.general "13.10.3.1General")),
the constraint is not satisfied[.](#temp.constr.concept-2.sentence-2)
Otherwise, let CI′ be
the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4Constraint normalization")) of the concept-id
after substitution of C[.](#temp.constr.concept-2.sentence-3)
[*Note [1](#temp.constr.concept-note-1)*:
Normalization of CI might be ill-formed; no diagnostics is required[.](#temp.constr.concept-2.sentence-4)
— *end note*]
[3](#temp.constr.concept-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1877)
To form CI′′,
each appearance of C's template parameters in
the parameter mappings of the atomic constraints
(including concept-dependent constraints)
in CI′ is substituted with their respective arguments from
the parameter mapping of CD and the arguments of CI[.](#temp.constr.concept-3.sentence-1)
[4](#temp.constr.concept-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1886)
CD is satisfied if CI′′ is satisfied[.](#temp.constr.concept-4.sentence-1)
[*Note [2](#temp.constr.concept-note-2)*:
Checking whether CI′′ is satisfied
can lead to further normalization of concept-dependent constraints[.](#temp.constr.concept-4.sentence-2)
— *end note*]
[*Example [1](#temp.constr.concept-example-1)*: template<typename>concept C = true;
template<typename T, template<typename> concept CC>concept D = CC<T>;
template<typename U, template<typename> concept CT, template<typename, template<typename> concept> concept CU>int f() requires CU<U, CT>;int i = f<int, C, D>();
In this example, the associated constraints of f consist of a concept-dependent constraint
whose expression is the concept-id CU<U, CT> with the mappingU↦U,CT↦CT,CU↦CU[.](#temp.constr.concept-4.sentence-3)
The result of substituting D into this expression is D<U, CT>[.](#temp.constr.concept-4.sentence-4)
We consider the normal form of the resulting concept-id,
which is CC<T> with the mappingT↦U,CC↦CT[.](#temp.constr.concept-4.sentence-5)
By recursion, C is substituted into CC<T>, and the result
is normalized to the atomic constraint true, which is satisfied[.](#temp.constr.concept-4.sentence-6)
— *end example*]
#### [13.5.2.5](#temp.constr.fold) Fold expanded constraint [[temp.constr.fold]](temp.constr.fold)
[1](#temp.constr.fold-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920)
A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5Fold expanded constraint[temp.constr.fold]") is formed from a constraint C and
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") which can either be && or ||[.](#temp.constr.fold-1.sentence-1)
A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#temp.constr.fold-1.sentence-2)
Let N be the number of elements
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#temp.constr.fold-1.sentence-3)
[2](#temp.constr.fold-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is && is satisfied if it is a valid pack expansion and
if N=0 or if for each i where 0≤i<N in increasing order,C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#temp.constr.fold-2.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is not satisfied[.](#temp.constr.fold-2.sentence-2)
[3](#temp.constr.fold-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1938)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is || is satisfied if it is a valid pack expansion,N>0, and if for i where 0≤i<N in increasing order,
there is a smallest i for which C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#temp.constr.fold-3.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is satisfied[.](#temp.constr.fold-3.sentence-2)
[4](#temp.constr.fold-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1948)
[*Note [1](#temp.constr.fold-note-1)*:
If the pack expansion expands packs of different size,
then it is invalid and the fold expanded constraint is not satisfied[.](#temp.constr.fold-4.sentence-1)
— *end note*]
[5](#temp.constr.fold-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1954)
Two fold expanded constraints are [*compatible for subsumption*](#def:subsumption,compatible_for "13.5.2.5Fold expanded constraint[temp.constr.fold]") if their respective constraints both contain
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#temp.constr.fold-5.sentence-1)

View File

@@ -0,0 +1,60 @@
[temp.constr.constr.general]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#constr.general)
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#general)
#### 13.5.2.1 General [temp.constr.constr.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1610)
A [*constraint*](#def:constraint "13.5.2.1General[temp.constr.constr.general]") is a sequence of logical operations and
operands that specifies requirements on template arguments[.](#1.sentence-1)
The operands of a logical operation are constraints[.](#1.sentence-2)
There are five different kinds of constraints:
- [(1.1)](#1.1)
conjunctions ([[temp.constr.op]](temp.constr.op "13.5.2.2Logical operations")),
- [(1.2)](#1.2)
disjunctions ([[temp.constr.op]](temp.constr.op "13.5.2.2Logical operations")),
- [(1.3)](#1.3)
atomic constraints ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints")),
- [(1.4)](#1.4)
concept-dependent constraints ([[temp.constr.concept]](temp.constr.concept "13.5.2.4Concept-dependent constraints")), and
- [(1.5)](#1.5)
fold expanded constraints ([[temp.constr.fold]](temp.constr.fold "13.5.2.5Fold expanded constraint"))[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1623)
In order for a constrained template to be instantiated ([[temp.spec]](temp.spec "13.9Template instantiation and specialization")),
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") shall be satisfied as described in the following subclauses[.](#2.sentence-1)
[*Note [1](#note-1)*:
Forming the name of a specialization of
a class template,
a variable template, or
an alias template ([[temp.names]](temp.names "13.3Names of template specializations"))
requires the satisfaction of its constraints[.](#2.sentence-2)
[Overload resolution](over.match.viable "12.2.3Viable functions[over.match.viable]") requires the satisfaction of constraints
on functions and function templates[.](#2.sentence-3)
— *end note*]

View File

@@ -0,0 +1,129 @@
[temp.constr.decl]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#decl)
### 13.5.3 Constrained declarations [temp.constr.decl]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1961)
A template declaration ([[temp.pre]](temp.pre "13.1Preamble"))
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")[.](#1.sentence-1)
This allows the specification of constraints for that declaration as
an expression:
[constraint-expression:](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15Logical OR operator[expr.log.or]")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1972)
Constraints can also be associated with a declaration through the use of[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") or parameter-type-list[.](#2.sentence-1)
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* that are used to constrain the declaration[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1979)
A declaration's [*associated constraints*](#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") are defined as follows:
- [(3.1)](#3.1)
If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s*,
the declaration has no associated constraints[.](#3.1.sentence-1)
- [(3.2)](#3.2)
Otherwise, if there is a single introduced [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]"),
the associated constraints are the [normal form](temp.constr.normal#def:normal_form,constraint "13.5.4Constraint normalization[temp.constr.normal]") of that expression[.](#3.2.sentence-1)
- [(3.3)](#3.3)
Otherwise, the associated constraints are the normal form of a [logicaland expression](expr.log.and "7.6.14Logical AND operator[expr.log.and]") whose operands are in the
following order:
* [(3.3.1)](#3.3.1)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")) in
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"),
in order of appearance, and
* [(3.3.2)](#3.3.2)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") following
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")), and
* [(3.3.3)](#3.3.3)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
each [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") in
the parameter-type-list of a function declaration, and
* [(3.3.4)](#3.3.4)
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") introduced by
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators")) of
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#3.3.sentence-1)
The formation of the associated constraints
establishes the order in which constraints are instantiated when checking
for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))[.](#3.sentence-2)
[*Example [1](#example-1)*: template<typename T> concept C = true;
template<C T> void f1(T);template<typename T> requires C<T> void f2(T);template<typename T> void f3(T) requires C<T>;
The functions f1, f2, and f3 have the associated
constraint C<T>[.](#3.sentence-3)
template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) > 0;
template<C1 T> void f4(T) requires C2<T>;template<typename T> requires C1<T> && C2<T> void f5(T);
The associated constraints of f4 and f5 are C1<T> ∧ C2<T>[.](#3.sentence-4)
template<C1 T> requires C2<T> void f6();template<C2 T> requires C1<T> void f7();
The associated constraints off6 are C1<T> ∧ C2<T>,
and those off7 are C2<T> ∧ C1<T>[.](#3.sentence-5)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2051)
When determining whether a given introduced[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") C1 of a declaration
in an instantiated specialization of a templated class
is equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") C2 of a declaration
outside the class body,C1 is instantiated[.](#4.sentence-1)
If the instantiation results in an invalid expression,
the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* are not equivalent[.](#4.sentence-2)
[*Note [1](#note-1)*:
This can happen when determining which member template is specialized
by an explicit specialization declaration[.](#4.sentence-3)
— *end note*]
[*Example [2](#example-2)*: template <class T> concept C = true;template <class T> struct A {template <class U> U f(U) requires C<typename T::type>; // #1template <class U> U f(U) requires C<T>; // #2};
template <> template <class U> U A<int>::f(U u) requires C<int> { return u; } // OK, specializes #2
Substituting int for T in C<typename T::type> produces an invalid expression, so the specialization does not match #1[.](#4.sentence-4)
Substituting int for T in C<T> produces C<int>,
which is equivalent to the [*constraint-expression*](#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") for the specialization,
so it does match #2[.](#4.sentence-5)
— *end example*]

View File

@@ -0,0 +1,63 @@
[temp.constr.fold]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#fold)
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.fold)
#### 13.5.2.5 Fold expanded constraint [temp.constr.fold]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1920)
A [*fold expanded constraint*](#def:constraint,fold_expanded "13.5.2.5Fold expanded constraint[temp.constr.fold]") is formed from a constraint C and
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") which can either be && or ||[.](#1.sentence-1)
A fold expanded constraint is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#1.sentence-2)
Let N be the number of elements
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1928)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is && is satisfied if it is a valid pack expansion and
if N=0 or if for each i where 0≤i<N in increasing order,C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#2.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is not satisfied[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1938)
A fold expanded constraint whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is || is satisfied if it is a valid pack expansion,N>0, and if for i where 0≤i<N in increasing order,
there is a smallest i for which C is satisfied
when replacing each pack expansion parameter
with the corresponding ith element[.](#3.sentence-1)
No substitution takes place for any i greater than
the smallest i for which the constraint is satisfied[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1948)
[*Note [1](#note-1)*:
If the pack expansion expands packs of different size,
then it is invalid and the fold expanded constraint is not satisfied[.](#4.sentence-1)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1954)
Two fold expanded constraints are [*compatible for subsumption*](#def:subsumption,compatible_for "13.5.2.5Fold expanded constraint[temp.constr.fold]") if their respective constraints both contain
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#5.sentence-1)

View File

@@ -0,0 +1,24 @@
[temp.constr.general]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#general)
### 13.5.1 General [temp.constr.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1595)
[*Note [1](#note-1)*:
Subclause [[temp.constr]](temp.constr "13.5Template constraints") defines the meaning of constraints on template arguments[.](#1.sentence-1)
The abstract syntax and satisfaction rules are defined
in [[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")[.](#1.sentence-2)
Constraints are associated with declarations in [[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations")[.](#1.sentence-3)
Declarations are partially ordered by their associated constraints ([[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints"))[.](#1.sentence-4)
— *end note*]

View File

@@ -0,0 +1,190 @@
[temp.constr.normal]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#normal)
### 13.5.4 Constraint normalization [temp.constr.normal]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2085)
The [*normal form*](#def:normal_form,constraint "13.5.4Constraint normalization[temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") E is
a [constraint](temp.constr.constr#def:constraint "13.5.2Constraints[temp.constr.constr]") that is defined as follows:
- [(1.1)](#1.1)
The normal form of an expression ( E ) is
the normal form of E[.](#1.1.sentence-1)
- [(1.2)](#1.2)
The normal form of an expression E1 || E2 is
the [disjunction](temp.constr.op#def:disjunction "13.5.2.2Logical operations[temp.constr.op]") of
the normal forms of E1 and E2[.](#1.2.sentence-1)
- [(1.3)](#1.3)
The normal form of an expression E1 && E2 is the conjunction of
the normal forms of E1 and E2[.](#1.3.sentence-1)
- [(1.4)](#1.4)
For a concept-id C<A1, A2, …, An> termed CI:
* [(1.4.1)](#1.4.1)
If C names a dependent concept,
the normal form of CI is a concept-dependent constraint
whose concept-id is CI and
whose parameter mapping is the identity mapping[.](#1.4.1.sentence-1)
* [(1.4.2)](#1.4.2)
Otherwise, to form CE,
any non-dependent concept template argument Ai is substituted into the [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") of C[.](#1.4.2.sentence-1)
If any such substitution results in an invalid concept-id,
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-2)
The normal form of CI is the result of substituting,
in the normal form N of CE,
appearances of C's template parameters
in the parameter mappings of the atomic constraints in N with their respective arguments from C[.](#1.4.2.sentence-3)
If any such substitution results in an invalid type or expression,
the program is ill-formed; no diagnostic is required[.](#1.4.2.sentence-4)
[*Example [1](#example-1)*: template<typename T> concept A = T::value || true;template<typename U> concept B = A<U*>;template<typename V> concept C = B<V&>;
Normalization of B's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is valid and results inT::value (with the mapping T↦U*) ∨ true (with an empty mapping),
despite the expression T::value being ill-formed
for a pointer type T[.](#1.4.sentence-2)
Normalization of C's [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") results in the program being ill-formed,
because it would form the invalid type V&* in the parameter mapping[.](#1.4.sentence-3)
— *end example*]
- [(1.5)](#1.5)
For a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7Fold expressions"))
that is either && or ||:
* [(1.5.1)](#1.5.1)
The normal form of an expression ( ... Op E ) is the normal form of ( E Op ... )[.](#1.5.1.sentence-1)
* [(1.5.2)](#1.5.2)
The normal form of an expression ( E1 Op ... Op E2 ) is the normal form of
+
[(1.5.2.1)](#1.5.2.1)
( E1 Op ... ) Op E2 if E1 contains an unexpanded pack, or
+
[(1.5.2.2)](#1.5.2.2)
E1 Op ( E2 Op ... ) otherwise[.](#1.5.2.sentence-1)
* [(1.5.3)](#1.5.3)
The normal form of an expression F of the form ( E Op ... ) is as follows:
If E contains an unexpanded concept template parameter pack,
it shall not contain an unexpanded template parameter pack of another kind[.](#1.5.3.sentence-2)
Let E′ be the normal form of E[.](#1.5.3.sentence-3)
+
[(1.5.3.1)](#1.5.3.1)
If E contains
an unexpanded concept template parameter pack Pk that
has corresponding template arguments in
the parameter mapping of any atomic constraint
(including concept-dependent constraints) of E′,
the number of arguments specified for all such Pk shall be the same number N[.](#1.5.3.1.sentence-1)
The normal form of F is the normal form of E0 Op Op EN−1 after substituting in Ei the respective ith concept argument of each Pk[.](#1.5.3.1.sentence-2)
If any such substitution results in an invalid type or expression,
the program is ill-formed; no diagnostic is required[.](#1.5.3.1.sentence-3)
+
[(1.5.3.2)](#1.5.3.2)
Otherwise,
the normal form of F is
a fold expanded constraint ([[temp.constr.fold]](temp.constr.fold "13.5.2.5Fold expanded constraint")) whose
constraint is E′ and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]") is Op[.](#1.5.3.2.sentence-1)
- [(1.6)](#1.6)
The normal form of any other expression E is
the atomic constraint
whose expression is E and
whose parameter mapping is the identity mapping[.](#1.6.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2201)
The process of obtaining the normal form of a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4Constraint normalization[temp.constr.normal]")[.](#2.sentence-1)
[*Note [1](#note-1)*:
Normalization of [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* is performed
when determining the associated constraints ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))
of a declaration
and
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5Names"))[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2217)
[*Example [2](#example-2)*: template<typename T> concept C1 = sizeof(T) == 1;template<typename T> concept C2 = C1<T> && 1 == 2;template<typename T> concept C3 = requires { typename T::type; };template<typename T> concept C4 = requires (T x) { ++x; };
template<C2 U> void f1(U); // #1template<C3 U> void f2(U); // #2template<C4 U> void f3(U); // #3
The associated constraints of #1 aresizeof(T) == 1 (with mapping T↦U) ∧ 1 == 2[.](#3.sentence-1)
The associated constraints of #2 arerequires { typename T::type; } (with mapping T↦U)[.](#3.sentence-2)
The associated constraints of #3 arerequires (T x) { ++x; } (with mapping T↦U)[.](#3.sentence-3)
— *end example*]
[*Example [3](#example-3)*: template<typename T>concept C = true;template<typename T, template<typename> concept CT>concept CC = CT<T>;
template<typename U, template<typename, template<typename> concept> concept CT>void f() requires CT<U*, C>;template<typename U>void g() requires CC<U*, C>;
The normal form of the associated constraints of f is
the concept-dependent constraint CT<T, C>[.](#3.sentence-4)
The normal form of the associated constraints of g is
the atomic constraint true[.](#3.sentence-5)
— *end example*]
[*Example [4](#example-4)*: template<typename T>concept A = true;template<typename T>concept B = A<T> && true; // B subsumes Atemplate<typename T>concept C = true;template<typename T>concept D = C<T> && true; // D subsumes Ctemplate<typename T, template<typename> concept... CTs>concept all_of = (CTs<T> && ...);
template<typename T> requires all_of<T, A, C>constexpr int f(T) { return 1; } // #1template<typename T> requires all_of<T, B, D>constexpr int f(T) { return 2; } // #2static_assert(f(1) == 2); // ok
The normal form of all_of<T, A, C> is
the conjunction of the normal forms of A<T> and C<T>[.](#3.sentence-6)
Similarly, the normal form of all_of<T, B, D> is
the conjunction of the normal forms of B<T> and D<T>[.](#3.sentence-7)
#2 therefore is more constrained than #1[.](#3.sentence-8)
— *end example*]
[*Example [5](#example-5)*: template<typename T, template<typename> concept>struct wrapper {};
template<typename... T, template<typename> concept... CTs>int f(wrapper<T, CTs>...) requires (CTs<T> && ...); // error: fold expression contains// different kinds of template parameters — *end example*]

105
cppdraft/temp/constr/op.md Normal file
View File

@@ -0,0 +1,105 @@
[temp.constr.op]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#op)
### 13.5.2 Constraints [[temp.constr.constr]](temp.constr.constr#temp.constr.op)
#### 13.5.2.2 Logical operations [temp.constr.op]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1640)
There are two binary logical operations on constraints: conjunction
and disjunction[.](#1.sentence-1)
[*Note [1](#note-1)*:
These logical operations have no corresponding C++ syntax[.](#1.sentence-2)
For the purpose of exposition, conjunction is spelled
using the symbol ∧ and disjunction is spelled using the
symbol ∨ [.](#1.sentence-3)
The operands of these operations are called the left
and right operands[.](#1.sentence-4)
In the constraint A ∧ B,A is the left operand, and B is the right operand[.](#1.sentence-5)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1653)
A [*conjunction*](#def:conjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#2.sentence-1)
To determine if a conjunction is[*satisfied*](#def:constraint,satisfaction,conjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#2.sentence-2)
If that is not satisfied, the conjunction is not satisfied[.](#2.sentence-3)
Otherwise, the conjunction is satisfied if and only if the second
operand is satisfied[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1664)
A [*disjunction*](#def:disjunction "13.5.2.2Logical operations[temp.constr.op]") is a constraint taking two
operands[.](#3.sentence-1)
To determine if a disjunction is[*satisfied*](#def:constraint,satisfaction,disjunction "13.5.2.2Logical operations[temp.constr.op]"),
the satisfaction of
the first operand is checked[.](#3.sentence-2)
If that is satisfied, the disjunction is satisfied[.](#3.sentence-3)
Otherwise, the disjunction is satisfied if and only if the second
operand is satisfied[.](#3.sentence-4)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1676)
[*Example [1](#example-1)*: template<typename T>constexpr bool get_value() { return T::value; }template<typename T>requires (sizeof(T) > 1) && (get_value<T>())void f(T); // has associated constraint sizeof(T) > 1 ∧ get_value<T>()void f(int);
f('a'); // OK, calls f(int)
In the satisfaction of the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") of f, the constraint sizeof(char) > 1 is not satisfied;
the second operand is not checked for satisfaction[.](#4.sentence-1)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L1695)
[*Note [2](#note-2)*:
A logical negation expression ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")) is an atomic constraint;
the negation operator is not treated as a logical operation on constraints[.](#5.sentence-1)
As a result, distinct negation [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints")[.](#5.sentence-2)
Furthermore, if substitution to determine
whether an atomic constraint is satisfied ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints"))
encounters a substitution failure, the constraint is not satisfied,
regardless of the presence of a negation operator[.](#5.sentence-3)
[*Example [2](#example-2)*: template <class T> concept sad = false;
template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); // ambiguous, !sad<T> atomic constraint expressions ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); // OK, !sad<T> atomic constraint expressions both come from not_sadtemplate <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); // error: associated constraints not satisfied due to substitution failuretemplate <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42); // OK, substitution failure contained within sad_nested_type
Here,requires (!sad<typename T::type>) requires
that there is a nested type that is not sad,
whereasrequires (!sad_nested_type<T>) requires
that there is no sad nested type[.](#5.sentence-4)
— *end example*]
— *end note*]

View File

@@ -0,0 +1,157 @@
[temp.constr.order]
# 13 Templates [[temp]](./#temp)
## 13.5 Template constraints [[temp.constr]](temp.constr#order)
### 13.5.5 Partial ordering by constraints [temp.constr.order]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2299)
A constraint P [*subsumes*](#def:constraint,subsumption "13.5.5Partial ordering by constraints[temp.constr.order]") a constraint Q if and only if,
for every disjunctive clause Pi in the disjunctive normal form[110](#footnote-110 "A constraint is in disjunctive normal form when it is a disjunction of clauses where each clause is a conjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the disjunctive normal form of the constraint A  ∧ (B ∨C) is (A ∧B)  ∨ (A ∧C). Its disjunctive clauses are (A ∧B) and (A ∧C).") of P, Pi subsumes every conjunctive clause Qj in the conjunctive normal form[111](#footnote-111 "A constraint is in conjunctive normal form when it is a conjunction of clauses where each clause is a disjunction of fold expanded or atomic constraints. For atomic constraints A, B, and C, the constraint A  ∧ (B ∨C) is in conjunctive normal form. Its conjunctive clauses are A and (B ∨C).") of Q, where
- [(1.1)](#1.1)
a disjunctive clause Pi subsumes a conjunctive clause Qj if and only
if there exists an atomic constraint Pia in Pi for which there exists
an atomic constraint Qjb in Qj such that Pia subsumes Qjb,
- [(1.2)](#1.2)
an atomic constraint A subsumes another atomic constraintB if and only if A and B are identical using the
rules described in [[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints"), and
- [(1.3)](#1.3)
a fold expanded constraint A subsumes
another fold expanded constraint B if they are compatible for subsumption,
have the same [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]"), and
the constraint of A subsumes that of B[.](#1.sentence-1)
[*Example [1](#example-1)*:
Let A and B be [atomic constraints](temp.constr.atomic#def:constraint,atomic "13.5.2.3Atomic constraints[temp.constr.atomic]")[.](#1.sentence-2)
The constraint A ∧ B subsumes A, but A does not subsume A ∧ B[.](#1.sentence-3)
The constraint A subsumes A ∨ B, but A ∨ B does not subsume A[.](#1.sentence-4)
Also note that every constraint subsumes itself[.](#1.sentence-5)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2354)
[*Note [1](#note-1)*:
The subsumption relation defines a partial ordering on constraints[.](#2.sentence-1)
This partial ordering is used to determine
- [(2.1)](#2.1)
the best viable candidate of non-template functions ([[over.match.best]](over.match.best "12.2.4Best viable function")),
- [(2.2)](#2.2)
the address of a non-template function ([[over.over]](over.over "12.3Address of an overload set")),
- [(2.3)](#2.3)
the matching of template template arguments ([[temp.arg.template]](temp.arg.template "13.4.4Template template arguments")),
- [(2.4)](#2.4)
the partial ordering of class template specializations ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3Partial ordering of partial specializations")), and
- [(2.5)](#2.5)
the partial ordering of function templates ([[temp.func.order]](temp.func.order "13.7.7.3Partial ordering of function templates"))[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2367)
The associated constraints C of a declaration Dare [*eligible for subsumption*](#def:eligible,for_subsumption "13.5.5Partial ordering by constraints[temp.constr.order]") unless C contains a concept-dependent constraint[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2378)
A declaration D1 is[*at least as constrained*](#def:at_least_as_constrained "13.5.5Partial ordering by constraints[temp.constr.order]") as
a declaration D2 if
- [(4.1)](#4.1)
D1 and D2 are both constrained declarations andD1's associated constraints
are eligible for subsumption and subsume those of D2; or
- [(4.2)](#4.2)
D2 has no associated constraints[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2390)
A declaration D1 is [*more constrained*](#def:more_constrained "13.5.5Partial ordering by constraints[temp.constr.order]") than another declaration D2 when D1 is at least as
constrained as D2, and D2 is not at least as
constrained as D1[.](#5.sentence-1)
[*Example [2](#example-2)*: template<typename T> concept C1 = requires(T t) { --t; };template<typename T> concept C2 = C1<T> && requires(T t) { *t; };
template<C1 T> void f(T); // #1template<C2 T> void f(T); // #2template<typename T> void g(T); // #3template<C1 T> void g(T); // #4 f(0); // selects #1 f((int*)0); // selects #2 g(true); // selects #3 because C1<bool> is not satisfied g(0); // selects #4 — *end example*]
[*Example [3](#example-3)*: template<template<typename T> concept CT, typename T>struct S {};template<typename T>concept A = true;
template<template<typename T> concept X, typename T>int f(S<X, T>) requires A<T> { return 42; } // #1template<template<typename T> concept X, typename T>int f(S<X, T>) requires X<T> { return 43; } // #2 f(S<A, int>{}); // ok, select #1 because #2 is not eligible for subsumption — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2427)
A non-template function F1 is [*more partial-ordering-constrained*](#def:more_partial-ordering-constrained "13.5.5Partial ordering by constraints[temp.constr.order]") than a non-template function F2 if
- [(6.1)](#6.1)
they have the same non-object-parameter-type-lists ([[dcl.fct]](dcl.fct "9.3.4.6Functions")), and
- [(6.2)](#6.2)
if they are member functions, both are direct members of the same class, and
- [(6.3)](#6.3)
if both are non-static member functions,
they have the same types for their object parameters, and
- [(6.4)](#6.4)
the declaration of F1 is more constrained than
the declaration of F2[.](#6.sentence-1)
[110)](#footnote-110)[110)](#footnoteref-110)
A constraint is in disjunctive normal form when it is a disjunction of
clauses where each clause is a conjunction of fold expanded or atomic constraints[.](#footnote-110.sentence-1)
For atomic constraints A, B, and C, the disjunctive normal form
of the constraintA ∧ (B ∨ C) is(A ∧ B) ∨ (A ∧ C)[.](#footnote-110.sentence-2)
Its disjunctive clauses are (A ∧ B) and (A ∧ C)[.](#footnote-110.sentence-3)
[111)](#footnote-111)[111)](#footnoteref-111)
A constraint is in conjunctive normal form when it is a conjunction
of clauses where each clause is a disjunction of fold expanded or atomic constraints[.](#footnote-111.sentence-1)
For atomic constraints A, B, and C, the constraintA ∧ (B ∨ C) is in conjunctive normal form[.](#footnote-111.sentence-2)
Its conjunctive clauses are A and (B ∨ C)[.](#footnote-111.sentence-3)

1903
cppdraft/temp/decls.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
[temp.decls.general]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#general)
### 13.7.1 General [temp.decls.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2592)
The template parameters of a template are specified in
the angle bracket enclosed list
that immediately follows the keyword template[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2597)
A [*primary template*](#def:template,primary "13.7.1General[temp.decls.general]") declaration is one
in which the name of the template is not followed by
a [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")[.](#2.sentence-1)
The template argument list of a primary template is
the template argument list of its [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template arguments"))[.](#2.sentence-2)
A template declaration in which the name of the template is followed by
a [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") is
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")) of
the template named in the declaration,
which shall be a class or variable template[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2609)
For purposes of name lookup and instantiation,
default arguments,[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s*,[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s* ([[temp.pre]](temp.pre "13.1Preamble")),
and[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")*s* of function templates
and
of member functions of class templates
are considered definitions;
each
default argument,[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"),[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"),
or[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") is a separate definition
which is unrelated
to the templated function definition or
to any other
default arguments,[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s*,[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s*,
or[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")*s*[.](#3.sentence-1)
For the purpose of instantiation, the substatements of a[constexpr if](stmt.if#def:constexpr_if "8.5.2The if statement[stmt.if]") statement are considered definitions[.](#3.sentence-2)
For the purpose of name lookup and instantiation,
the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7Expansion statements[stmt.expand]") is considered a template definition[.](#3.sentence-3)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2641)
Because an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]") cannot declare a[*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"), it is not possible to partially or
explicitly specialize an alias template[.](#4.sentence-1)

1462
cppdraft/temp/deduct.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,208 @@
[temp.deduct.call]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.call)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#call)
#### 13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8146)
Template argument deduction is done by comparing each function
template parameter type (call itP)
that contains template parameters that participate in template argument deduction
with the type of the corresponding argument of the call (call itA)
as described below[.](#1.sentence-1)
If removing references and cv-qualifiers from P givesstd::initializer_list<€²> or P′[N] for some P′ and N and the
argument is a non-empty initializer list ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")), then deduction is
performed instead for each element of the initializer list independently,
taking P′ as separate function template parameter types P′i and the ith initializer element as the corresponding argument[.](#1.sentence-2)
In the P′[N] case, if N is a constant template parameter,N is deduced from the length of the initializer list[.](#1.sentence-3)
Otherwise, an initializer list argument causes the
parameter to be considered a non-deduced context ([[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type"))[.](#1.sentence-4)
[*Example [1](#example-1)*: template<class T> void f(std::initializer_list<T>);
f({1,2,3}); // T deduced as int f({1,"asdf"}); // error: T deduced as both int and const char*template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for Ttemplate<class T, int N> void h(T const(&)[N]);
h({1,2,3}); // T deduced as int; N deduced as 3template<class T> void j(T const(&)[3]);
j({42}); // T deduced as int; array bound not consideredstruct Aggr { int i; int j; };template<int N> void k(Aggr const(&)[N]);
k({1,2,3}); // error: deduction fails, no conversion from int to Aggr k({{1},{2},{3}}); // OK, N deduced as 3template<int M, int N> void m(int const(&)[M][N]);
m({{1,2},{3,4}}); // M and N both deduced as 2template<class T, int N> void n(T const(&)[N], T);
n({{1},{2},{3}},Aggr()); // OK, T is Aggr, N is 3template<typename T, int N> void o(T (* const (&)[N])(T)) { }int f1(int);int f4(int);char f4(char);
o({ &f1, &f4 }); // OK, T deduced as int from first element, nothing// deduced from second element, N deduced as 2 o({ &f1, static_cast<char(*)(char)>(&f4) }); // error: conflicting deductions for T — *end example*]
For a function parameter pack that occurs at the end
of the [*parameter-declaration-list*](dcl.fct#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]"),
deduction is performed for each remaining argument of the call,
taking the type P of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of the function parameter pack
as the corresponding function template parameter type[.](#1.sentence-5)
Each deduction deduces template arguments for subsequent positions in
the template parameter packs expanded by the function parameter pack[.](#1.sentence-6)
When a function parameter pack appears in a non-deduced
context ([[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type")), the type of that pack is
never deduced[.](#1.sentence-7)
[*Example [2](#example-2)*: template<class ... Types> void f(Types& ...);template<class T1, class ... Types> void g(T1, Types ...);template<class T1, class ... Types> void g1(Types ..., T1);
void h(int x, float& y) {const int z = x;
f(x, y, z); // Types deduced as int, float, const int g(x, y, z); // T1 deduced as int; Types deduced as float, int g1(x, y, z); // error: Types is not deduced g1<int, int, int>(x, y, z); // OK, no deduction occurs} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8229)
IfP is not a reference type:
- [(2.1)](#2.1)
IfA is an array type, the pointer type produced by the [array-to-pointer
standard conversion](conv.array "7.3.3Array-to-pointer conversion[conv.array]") is used in place ofA for type deduction;
otherwise,
- [(2.2)](#2.2)
IfA is a function type, the pointer type produced by the[function-to-pointer standard conversion](conv.func "7.3.4Function-to-pointer conversion[conv.func]") is used in place
ofA for type
deduction; otherwise,
- [(2.3)](#2.3)
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
type are ignored for type deduction[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8259)
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
type are ignored for type deduction[.](#3.sentence-1)
IfP is a reference type, the type
referred to byP is used for type deduction[.](#3.sentence-2)
[*Example [3](#example-3)*: template<class T> int f(const T&);int n1 = f(5); // calls f<int>(const int&)const int i = 0;int n2 = f(i); // calls f<int>(const int&)template <class T> int g(volatile T&);int n3 = g(i); // calls g<const int>(const volatile int&) — *end example*]
A [*forwarding reference*](#def:forwarding_reference "13.10.3.2Deducing template arguments from a function call[temp.deduct.call]") is an rvalue reference to a cv-unqualified template parameter
that does not represent a template parameter of a class template
(during class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction")))[.](#3.sentence-3)
If P is a forwarding reference and the argument is an
lvalue, the type “lvalue reference to A” is used in place of A for type
deduction[.](#3.sentence-4)
[*Example [4](#example-4)*: template <class T> int f(T&& heisenreference);template <class T> int g(const T&&);int i;int n1 = f(i); // calls f<int&>(int&)int n2 = f(0); // calls f<int>(int&&)int n3 = g(i); // error: would call g<int>(const int&&), which// would bind an rvalue reference to an lvaluetemplate <class T> struct A {template <class U> A(T&&, U&&, int*); // #1: T&& is not a forwarding reference.// U&& is a forwarding reference. A(T&&, int*); // #2};
template <class T> A(T&&, int*) -> A<T>; // #3: T&& is a forwarding reference.int *ip;
A a{i, 0, ip}; // error: cannot deduce from #1 A a0{0, 0, ip}; // uses #1 to deduce A<int> and #1 to initialize A a2{i, ip}; // uses #3 to deduce A<int&> and #2 to initialize — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8315)
In general, the deduction process attempts to find template argument
values that will make the deducedA identical toA (after
the typeA is transformed as described above)[.](#4.sentence-1)
However, there are
three cases that allow a difference:
- [(4.1)](#4.1)
If the originalP is a reference type, the deducedA (i.e.,
the type referred to by the reference) can be more cv-qualified than
the transformed A[.](#4.1.sentence-1)
- [(4.2)](#4.2)
The transformed A can be another pointer or pointer-to-member type that can be converted
to the deducedA via a [function pointer conversion](conv.fctptr "7.3.14Function pointer conversions[conv.fctptr]") and/or[qualification conversion](conv.qual "7.3.6Qualification conversions[conv.qual]")[.](#4.2.sentence-1)
- [(4.3)](#4.3)
IfP is a class andP has the form[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
then
the transformed A can be a derived class D of the
deducedA[.](#4.3.sentence-1)
Likewise, ifP is a pointer to a class of the form[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
the transformed A can be a pointer to a
derived class D of the class pointed to by the deducedA[.](#4.3.sentence-2)
However, if there is a class C that is
a (direct or indirect) base class of D and
derived (directly or indirectly) from a class B and
that would be a valid deduced A,
the deduced A cannot be B or pointer to B,
respectively[.](#4.3.sentence-3)
[*Example [5](#example-5)*: template <typename... T> struct X;template <> struct X<> {};template <typename T, typename... Ts>struct X<T, Ts...> : X<Ts...> {};struct D : X<int> {};struct E : X<>, X<int> {};
template <typename... T>int f(const X<T...>&);int x = f(D()); // calls f<int>, not f<>// B is X<>, C is X<int>int z = f(E()); // calls f<int>, not f<> — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8390)
These alternatives are considered only if type deduction would
otherwise fail[.](#5.sentence-1)
If they yield more than one possible deducedA,
the type deduction fails[.](#5.sentence-2)
[*Note [1](#note-1)*:
If a template parameter
is not used in any of the function parameters of a function template,
or is used only in a non-deduced context, its corresponding[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") cannot be deduced from a function call and the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") must be explicitly specified[.](#5.sentence-3)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8406)
WhenP is a function type, function pointer type, or pointer-to-member-function type:
- [(6.1)](#6.1)
If the argument is an overload set containing one or more function templates,
the parameter is treated as a non-deduced context[.](#6.1.sentence-1)
- [(6.2)](#6.2)
If the argument is an overload set (not containing function templates), trial
argument deduction is attempted using each of the members of the set
whose associated constraints ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")) are satisfied[.](#6.2.sentence-1)
If all successful deductions yield the same deduced A,
that deduced A is the result of deduction;
otherwise, the parameter is treated as a non-deduced context[.](#6.2.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8423)
[*Example [6](#example-6)*: // Only one function of an overload set matches the call so the function parameter is a deduced context.template <class T> int f(T (*p)(T));int g(int);int g(char);int i = f(g); // calls f(int (*)(int)) — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8434)
[*Example [7](#example-7)*: // Ambiguous deduction causes the second function parameter to be a non-deduced context.template <class T> int f(T, T (*p)(T));int g(int);char g(char);int i = f(1, g); // calls f(int, int (*)(int)) — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8445)
[*Example [8](#example-8)*: // The overload set contains a template, causing the second function parameter to be a non-deduced context.template <class T> int f(T, T (*p)(T));char g(char);template <class T> T g(T);int i = f(1, g); // calls f(int, int (*)(int)) — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8456)
[*Example [9](#example-9)*: // All arguments for placeholder type deduction ([[dcl.type.auto.deduct]](dcl.type.auto.deduct "9.2.9.7.2Placeholder type deduction")) yield the same deduced type.template<bool B> struct X {static void f(short) requires B; // #1static void f(short); // #2};void test() {auto x = &X<true>::f; // OK, deduces void(*)(short), selects #1auto y = &X<false>::f; // OK, deduces void(*)(short), selects #2} — *end example*]

View File

@@ -0,0 +1,93 @@
[temp.deduct.conv]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.conv)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#conv)
#### 13.10.3.4 Deducing conversion function template arguments [temp.deduct.conv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8494)
Template argument deduction is done by comparing the return type of
the
conversion function template
(call itP)
with the type specified by the [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") of the[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") being looked up
(call it A) as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type")[.](#1.sentence-1)
If the [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") is constructed during
overload resolution ([[over.match.funcs]](over.match.funcs "12.2.2Candidate functions and argument lists")),
the rules in the remainder of this subclause apply[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8507)
If P is a reference type, the type referred to by P is used in place
of P for type deduction and for any further references to or transformations ofP in the remainder of this subclause[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8512)
IfA is not a reference type:
- [(3.1)](#3.1)
IfP is an array type, the pointer type produced by the[array-to-pointer standard conversion](conv.array "7.3.3Array-to-pointer conversion[conv.array]") is used in place ofP for type
deduction; otherwise,
- [(3.2)](#3.2)
IfP is a function type, the pointer type produced by the[function-to-pointer standard conversion](conv.func "7.3.4Function-to-pointer conversion[conv.func]") is used in place ofP for
type deduction; otherwise,
- [(3.3)](#3.3)
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
type are ignored for type deduction[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8541)
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
type are ignored for type deduction[.](#4.sentence-1)
IfA is a
reference type, the type referred to byA is used for type deduction[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8554)
In general, the deduction process attempts to find template argument
values that will make the deducedA identical toA[.](#5.sentence-1)
However, certain attributes of A may be ignored:
- [(5.1)](#5.1)
If the original A is a reference type,
any cv-qualifiers of A (i.e., the type referred to by the reference)[.](#5.1.sentence-1)
- [(5.2)](#5.2)
If the original A is
a function pointer or pointer-to-member-function type
with a potentially-throwing exception specification ([[except.spec]](except.spec "14.5Exception specifications")),
the exception specification[.](#5.2.sentence-1)
- [(5.3)](#5.3)
Any cv-qualifiers in A that can be restored by a qualification conversion[.](#5.3.sentence-1)
These attributes are ignored only if type deduction would
otherwise fail[.](#5.sentence-3)
If ignoring them allows more than one possible deducedA,
the type deduction fails[.](#5.sentence-4)

View File

@@ -0,0 +1,41 @@
[temp.deduct.decl]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.decl)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#decl)
#### 13.10.3.7 Deducing template arguments from a function declaration [temp.deduct.decl]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9479)
In a declaration whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") refers to a specialization
of a function template, template argument deduction is performed to identify
the specialization to which the declaration refers[.](#1.sentence-1)
Specifically, this is done
for [explicit instantiations](temp.explicit "13.9.3Explicit instantiation[temp.explicit]"), [explicit specializations](temp.expl.spec "13.9.4Explicit specialization[temp.expl.spec]"),
and certain [friend declarations](temp.friend "13.7.5Friends[temp.friend]")[.](#1.sentence-2)
This is also done to
determine whether a deallocation function template specialization matches a placementoperator new ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"), [[expr.new]](expr.new "7.6.2.8New"))[.](#1.sentence-3)
In all these cases, P is the type of the function template being considered
as a potential match and A is either the function type from the
declaration
or the type of the deallocation function that would match the placementoperator new as described in [[expr.new]](expr.new "7.6.2.8New")[.](#1.sentence-4)
The
deduction is done as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type")[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9494)
If, for the set of function templates so considered, there is either no match or
more than one match after partial ordering has been considered ([[temp.func.order]](temp.func.order "13.7.7.3Partial ordering of function templates")),
deduction fails and, in the declaration cases, the
program is ill-formed[.](#2.sentence-1)

View File

@@ -0,0 +1,35 @@
[temp.deduct.funcaddr]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.funcaddr)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#funcaddr)
#### 13.10.3.3 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8473)
Template arguments can be deduced from the type specified when taking
the address of an [overload set](over.over "12.3Address of an overload set[over.over]")[.](#1.sentence-1)
If there is a target,
the function template's function type and the target type
are used as the types ofP andA,
and the deduction is done as
described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type")[.](#1.sentence-2)
Otherwise, deduction is performed with empty sets of types P and A[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8486)
A placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")) in the return type of a
function template is a non-deduced context[.](#2.sentence-1)
If template argument
deduction succeeds for such a function, the return type is determined
from instantiation of the function body[.](#2.sentence-2)

View File

@@ -0,0 +1,368 @@
[temp.deduct.general]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.general)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#general)
#### 13.10.3.1 General [temp.deduct.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7733)
When a
function template
specialization is referenced, all of the
template arguments shall have values[.](#1.sentence-1)
The values can be
explicitly specified or, in some cases, be deduced from the use
or obtained from default[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*[.](#1.sentence-2)
[*Example [1](#example-1)*:
void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); // calls sort(Array<dcomplex>&) sort(ci); // calls sort(Array<int>&)} andvoid g(double d) {int i = convert<int>(d); // calls convert<int,double>(double)int c = convert<char>(d); // calls convert<char,double>(double)}
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7758)
When an explicit template argument list is specified, if the
given [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is not valid ([[temp.names]](temp.names "13.3Names of template specializations")),
type deduction fails[.](#2.sentence-1)
Otherwise, the specified template argument values are substituted for the
corresponding template parameters as specified below[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7766)
After this substitution is performed, the function parameter type
adjustments described in [[dcl.fct]](dcl.fct "9.3.4.6Functions") are performed[.](#3.sentence-1)
[*Example [2](#example-2)*:
A parameter type of “void (const int, int[5])” becomes
“void(*)(int,int*)”[.](#3.sentence-2)
— *end example*]
[*Note [1](#note-1)*:
A top-level qualifier in a function parameter declaration does not affect
the function type but still affects the type of the function parameter
variable within the function[.](#3.sentence-3)
— *end note*]
[*Example [3](#example-3)*: template <class T> void f(T t);template <class X> void g(const X x);template <class Z> void h(Z, Z*);
int main() {// #1: function type is f(int), t is non const f<int>(1); // #2: function type is f(int), t is const f<const int>(1); // #3: function type is g(int), x is const g<int>(1); // #4: function type is g(int), x is const g<const int>(1); // #5: function type is h(int, const int*) h<const int>(1,0);} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7803)
[*Note [2](#note-2)*:
f<int>(1) and f<const int>(1) call distinct functions
even though both of the functions called have the same function type[.](#4.sentence-1)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7809)
The resulting substituted and adjusted function type is used as
the type of the function template for template argument
deduction[.](#5.sentence-1)
If a template argument has not been deduced and its
corresponding template parameter has a default argument, the
template argument is determined by substituting the template
arguments determined for preceding template parameters into the
default argument[.](#5.sentence-2)
If the substitution results in an invalid type,
as described above, type deduction fails[.](#5.sentence-3)
[*Example [4](#example-4)*: template <class T, class U = double>void f(T t = 0, U u = 0);
void g() { f(1, 'c'); // f<int,char>(1,'c') f(1); // f<int,double>(1,0) f(); // error: T cannot be deduced f<int>(); // f<int,double>(0,0) f<int,char>(); // f<int,char>(0,0)} — *end example*]
When all template arguments have been deduced or obtained from
default template arguments, all uses of template parameters in
the template parameter list of the template
are replaced with the corresponding deduced
or default argument values[.](#5.sentence-4)
If the substitution results in an
invalid type, as described above, type deduction fails[.](#5.sentence-5)
If the function template has associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations")),
those constraints are checked for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))[.](#5.sentence-6)
If the constraints are not satisfied, type deduction fails[.](#5.sentence-7)
In the context of a function call, if type deduction has not yet failed, then
for those function parameters for which the function call has arguments,
each function parameter with a type that was non-dependent
before substitution of any explicitly-specified template arguments
is checked against its corresponding argument;
if the corresponding argument cannot be implicitly converted
to the parameter type, type deduction fails[.](#5.sentence-8)
[*Note [3](#note-3)*:
Overload resolution will check the other parameters, including
parameters with dependent types in which
no template parameters participate in template argument deduction and
parameters that became non-dependent due to substitution of
explicitly-specified template arguments[.](#5.sentence-9)
— *end note*]
If type deduction has not yet failed, then
all uses of template parameters in the function type are
replaced with the corresponding deduced or default argument values[.](#5.sentence-10)
If the substitution results in an invalid type, as described above,
type deduction fails[.](#5.sentence-11)
[*Example [5](#example-5)*: template <class T> struct Z {typedef typename T::x xx;};template <class T> concept C = requires { typename T::A; };template <C T> typename Z<T>::xx f(void *, T); // #1template <class T> void f(int, T); // #2struct A {} a;struct ZZ {template <class T, class = typename Z<T>::xx> operator T *(); operator int();};int main() { ZZ zz;
f(1, a); // OK, deduction fails for #1 because there is no conversion from int to void* f(zz, 42); // OK, deduction fails for #1 because C<int> is not satisfied} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7882)
At certain points in the template argument deduction process it is necessary
to take a function type that makes use of template parameters and replace those
template parameters with the corresponding template arguments[.](#6.sentence-1)
This is done at
the beginning of template argument deduction when any explicitly specified
template arguments are substituted into the function type, and again at the end
of template argument deduction when any template arguments that were deduced or
obtained from default arguments are substituted[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7891)
The [*deduction substitution loci*](#def:deduction_substitution_loci "13.10.3.1General[temp.deduct.general]") are
- [(7.1)](#7.1)
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]"),
- [(7.2)](#7.2)
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]"),
- [(7.3)](#7.3)
the template parameter declarations, and
- [(7.4)](#7.4)
the template argument list of a partial specialization ([[temp.spec.partial.general]](temp.spec.partial.general "13.7.6.1General"))[.](#7.sentence-1)
The substitution occurs in all types and expressions that are used
in the deduction substitution loci[.](#7.sentence-2)
The expressions include not only
constant expressions such as those that appear in array bounds or as nontype
template arguments but also general expressions (i.e., non-constant expressions)
inside sizeof, decltype, and other contexts that allow non-constant
expressions[.](#7.sentence-3)
The substitution proceeds in lexical order and stops when
a condition that causes deduction to fail is encountered[.](#7.sentence-4)
If substitution into different declarations of the same function template would
cause template instantiations to occur in a different order or not at all,
the program is ill-formed; no diagnostic required[.](#7.sentence-5)
[*Note [4](#note-4)*:
The equivalent substitution in
exception specifications ([[except.spec]](except.spec "14.5Exception specifications"))
and function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))
is done only when
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1General[dcl.contract.func]"), respectively,
is instantiated,
at which point a program is ill-formed
if the substitution results in an invalid type or expression[.](#7.sentence-6)
— *end note*]
[*Example [6](#example-6)*: template <class T> struct A { using X = typename T::X; };template <class T> typename T::X f(typename A<T>::X);template <class T> void f(...) { }template <class T> auto g(typename A<T>::X) -> typename T::X;template <class T> void g(...) { }template <class T> typename T::X h(typename A<T>::X);template <class T> auto h(typename A<T>::X) -> typename T::X; // redeclarationtemplate <class T> void h(...) { }void x() { f<int>(0); // OK, substituting return type causes deduction to fail g<int>(0); // error, substituting parameter type instantiates A<int> h<int>(0); // ill-formed, no diagnostic required} — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7941)
If a substitution results in an invalid type or expression, type deduction fails[.](#8.sentence-1)
An
invalid type or expression is one that would be ill-formed, with a diagnostic
required, if written in the same context using the substituted arguments[.](#8.sentence-2)
[*Note [5](#note-5)*:
If no diagnostic is required, the program is still ill-formed[.](#8.sentence-3)
Access checking is done as part of the substitution process[.](#8.sentence-4)
— *end note*]
Invalid types and expressions can result in a deduction failure
only in the immediate context of the deduction substitution loci[.](#8.sentence-5)
[*Note [6](#note-6)*:
The substitution into types and expressions can result
in effects such as the instantiation of class template specializations and/or
function template specializations, the generation of implicitly-defined functions,
etc[.](#8.sentence-6)
Such effects are not in the “immediate context” and can result in the
program being ill-formed[.](#8.sentence-7)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7959)
When substituting into a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"),
substitution into its body is not in the immediate context[.](#9.sentence-1)
[*Note [7](#note-7)*:
The intent is to avoid requiring implementations to deal with
substitution failure involving arbitrary statements[.](#9.sentence-2)
[*Example [7](#example-7)*: template <class T>auto f(T) -> decltype([]() { T::invalid; } ());void f(...);
f(0); // error: invalid expression not part of the immediate contexttemplate <class T, std::size_t = sizeof([]() { T::invalid; })>void g(T);void g(...);
g(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto h(T) -> decltype([x = T::invalid]() { });void h(...);
h(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto i(T) -> decltype([]() -> typename T::invalid { });void i(...);
i(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1void j(...); // #2 j(0); // deduction fails on #1, calls #2 — *end example*]
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7995)
[*Example [8](#example-8)*: struct X { };struct Y { Y(X) {}};
template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1 X f(Y, Y); // #2 X x1, x2;
X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2 — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8011)
[*Note [8](#note-8)*:
Type deduction can fail for the following reasons:
- [(11.1)](#11.1)
Attempting to instantiate a pack expansion containing multiple packs of differing lengths[.](#11.1.sentence-1)
- [(11.2)](#11.2)
Attempting to create an array with an element type that is void, a
function type, or a reference type, or attempting
to create an array with a size that is zero or negative[.](#11.2.sentence-1)
[*Example [9](#example-9)*: template <class T> int f(T[5]);int I = f<int>(0);int j = f<void>(0); // invalid array — *end example*]
- [(11.3)](#11.3)
Attempting to use a type that is not a class or enumeration type in a qualified name[.](#11.3.sentence-1)
[*Example [10](#example-10)*: template <class T> int f(typename T::B*);int i = f<int>(0); — *end example*]
- [(11.4)](#11.4)
Attempting to use a type in a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") when
that type does not contain the specified member, or
* [(11.4.1)](#11.4.1)
the specified member is not a type where a type is required, or
* [(11.4.2)](#11.4.2)
the specified member is not a template where a template is required, or
* [(11.4.3)](#11.4.3)
the specified member is not a non-type, non-template where a non-type,
non-template is required[.](#11.4.sentence-1)
[*Example [11](#example-11)*: template <int I> struct X { };template <template <class T> class> struct Z { };template <class T> void f(typename T::Y*) {}template <class T> void g(X<T::N>*) {}template <class T> void h(Z<T::TT>*) {}struct A {};struct B { int Y; };struct C {typedef int N;};struct D {typedef int TT;};
int main() {// Deduction fails in each of these cases: f<A>(0); // A does not contain a member Y f<B>(0); // The Y member of B is not a type g<C>(0); // The N member of C is not a non-type, non-template name h<D>(0); // The TT member of D is not a template} — *end example*]
- [(11.5)](#11.5)
Attempting to create a pointer to reference type[.](#11.5.sentence-1)
- [(11.6)](#11.6)
Attempting to create a reference to void[.](#11.6.sentence-1)
- [(11.7)](#11.7)
Attempting to create “pointer to member of T” when T is not a
class type[.](#11.7.sentence-1)
[*Example [12](#example-12)*: template <class T> int f(int T::*);int i = f<int>(0); — *end example*]
- [(11.8)](#11.8)
Attempting to give an invalid type to a constant template parameter[.](#11.8.sentence-1)
[*Example [13](#example-13)*: template <class T, T> struct S {};template <class T> int f(S<T, T{}>*); // #1class X {int m;};int i0 = f<X>(0); // #1 uses a value of non-structural type X as a constant template argument — *end example*]
- [(11.9)](#11.9)
Attempting to perform an invalid conversion in either a template
argument expression, or an expression used in the function
declaration[.](#11.9.sentence-1)
[*Example [14](#example-14)*: template <class T, T*> int f(int);int i2 = f<int,1>(0); // can't convert 1 to int* — *end example*]
- [(11.10)](#11.10)
Attempting to create a function type in which a parameter has a type
of void, or in which the return type is a function type
or array type[.](#11.10.sentence-1)
- [(11.11)](#11.11)
Attempting to give to
an explicit object parameter of a lambda's function call operator
a type not permitted for such ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types"))[.](#11.11.sentence-1)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8124)
[*Example [15](#example-15)*:
In the following example,
assuming a signed char cannot represent the value 1000,
a [narrowing conversion](dcl.init.list#def:conversion,narrowing "9.5.5List-initialization[dcl.init.list]") would be required
to convert the [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") of type int to signed char,
therefore substitution fails for the
second template ([[temp.arg.nontype]](temp.arg.nontype "13.4.3Constant template arguments"))[.](#12.sentence-1)
template <int> int f(int);template <signed char> int f(int);int i1 = f<1000>(0); // OKint i2 = f<1>(0); // ambiguous; not narrowing — *end example*]

View File

@@ -0,0 +1,57 @@
[temp.deduct.guide]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.deduct.guide)
### 13.7.2 Class templates [[temp.class]](temp.class#temp.deduct.guide)
#### 13.7.2.3 Deduction guides [temp.deduct.guide]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2823)
Deduction guides are used
when a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") appears as a type specifier
for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))[.](#1.sentence-1)
Deduction guides are not found by name lookup[.](#1.sentence-2)
Instead, when performing class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction")),
all reachable deduction guides declared for the class template are considered[.](#1.sentence-3)
[deduction-guide:](#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]")
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")opt ;
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2837)
[*Example [1](#example-1)*: template<class T, class D = int>struct S { T data;};template<class U> S(U) -> S<typename U::type>;
struct A {using type = short; operator type();};
S x{A()}; // x is of type S<short, int> — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2855)
The same restrictions apply
to the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of a deduction guide
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of
a deduction guide[.](#3.sentence-1)
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") shall name a class template specialization[.](#3.sentence-2)
The [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#3.sentence-3)
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]") shall inhabit the scope
to which the corresponding class template belongs
and, for a member class template, have the same access[.](#3.sentence-4)
Two deduction guide declarations
for the same class template
shall not have equivalent [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")*s* if either is reachable from the other[.](#3.sentence-5)

View File

@@ -0,0 +1,219 @@
[temp.deduct.partial]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.partial)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#partial)
#### 13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8583)
Template argument deduction is done by comparing certain types associated with
the two function templates being compared[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8587)
Two sets of types are used to determine the partial ordering[.](#2.sentence-1)
For each of
the templates involved there is the original function type and the
transformed function type[.](#2.sentence-2)
[*Note [1](#note-1)*:
The creation of the transformed type is described in [[temp.func.order]](temp.func.order "13.7.7.3Partial ordering of function templates")[.](#2.sentence-3)
— *end note*]
The deduction process uses the
transformed type as the argument template and the original type of the
other template as the parameter template[.](#2.sentence-4)
This process is done twice
for each type involved in the partial ordering comparison: once using
the transformed template-1 as the argument template and template-2 as
the parameter template and again using the transformed template-2 as
the argument template and template-1 as the parameter template[.](#2.sentence-5)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8602)
The types used to determine the ordering depend on the context in which
the partial ordering is done:
- [(3.1)](#3.1)
In the context of a function call, the types used are those function parameter types
for which the function call has arguments[.](#3.1.sentence-1)[119](#footnote-119 "Default arguments are not considered to be arguments in this context; they only become arguments after a function has been selected.")
- [(3.2)](#3.2)
In the context of a call to a conversion function, the return types of
the conversion function templates are used[.](#3.2.sentence-1)
- [(3.3)](#3.3)
In [other contexts](temp.func.order "13.7.7.3Partial ordering of function templates[temp.func.order]") the function template's function
type is used[.](#3.3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8622)
Each type nominated above from the parameter template and the corresponding type from the
argument template are used as the types ofP andA[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8629)
Before the partial ordering is done, certain transformations are performed
on the types used for partial ordering:
- [(5.1)](#5.1)
IfP is a reference type,P is replaced by the type referred to[.](#5.1.sentence-1)
- [(5.2)](#5.2)
IfA is a reference type,A is replaced by the type referred to[.](#5.2.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8647)
If bothP andA were reference types (before being replaced with the type referred to
above), determine which of the two types (if any) is more cv-qualified
than the other; otherwise the types are considered to be equally
cv-qualified for partial ordering purposes[.](#6.sentence-1)
The result of this
determination will be used below[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8658)
Remove any top-level cv-qualifiers:
- [(7.1)](#7.1)
IfP is a cv-qualified type,P is replaced by the cv-unqualified version ofP[.](#7.1.sentence-1)
- [(7.2)](#7.2)
IfA is a cv-qualified type,A is replaced by the cv-unqualified version ofA[.](#7.2.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8677)
Using the resulting typesP andA,
the deduction is then done as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type")[.](#8.sentence-1)
If P is a function parameter pack, the type A of each remaining
parameter type of the argument template is compared with the type P of
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of the function parameter pack[.](#8.sentence-2)
Each comparison
deduces template arguments for subsequent positions in the template parameter
packs expanded by the function parameter pack[.](#8.sentence-3)
Similarly, if A was transformed from a function parameter pack,
it is compared with each remaining parameter type of the parameter template[.](#8.sentence-4)
If deduction succeeds for a given type,
the type from the argument template is considered to be at least as specialized
as the type from the parameter template[.](#8.sentence-5)
[*Example [1](#example-1)*: template<class... Args> void f(Args... args); // #1template<class T1, class... Args> void f(T1 a1, Args... args); // #2template<class T1, class T2> void f(T1 a1, T2 a2); // #3 f(); // calls #1 f(1, 2, 3); // calls #2 f(1, 2); // calls #3; non-variadic template #3 is more specialized// than the variadic templates #1 and #2 — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8706)
If, for a given type, the
types are identical after the transformations above
and both P and A were reference types (before being replaced with the
type referred to above):
- [(9.1)](#9.1)
if the type from the argument template was an lvalue reference and the type
from the parameter template was not,
the parameter type is not considered to be
at least as specialized as the argument type; otherwise,
- [(9.2)](#9.2)
if the type from
the argument template is more cv-qualified than the type from the
parameter template (as described above),
the parameter type is not considered to be
at least as specialized as the argument type[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8723)
Function template F is [*at least as specialized as*](#def:more_specialized "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]") function template G if,
for each pair of types used to determine the ordering,
the type from F is at least as specialized as
the type from G[.](#10.sentence-1)
F is [*more specialized than*](#def:more_specialized,function_template "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]")G ifF is at least as specialized asG andG is not at least as specialized asF[.](#10.sentence-2)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8742)
If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and
if G has a trailing function parameter pack
for which F does not have a corresponding parameter, and
if F does not have a trailing function parameter pack,
then F is more specialized than G[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8750)
In most cases,
deduction fails if not all template parameters have values,
but for partial ordering purposes a template
parameter may remain without a value provided it is not used in the
types being used for partial ordering[.](#12.sentence-1)
[*Note [2](#note-2)*:
A template parameter used in a non-deduced context is considered used[.](#12.sentence-2)
— *end note*]
[*Example [2](#example-2)*: template <class T> T f(int); // #1template <class T, class U> T f(U); // #2void g() { f<int>(1); // calls #1} — *end example*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8769)
[*Note [3](#note-3)*:
Partial ordering of function templates containing
template parameter packs is independent of the number of deduced arguments
for those template parameter packs[.](#13.sentence-1)
— *end note*]
[*Example [3](#example-3)*: template<class ...> struct Tuple { };template<class ... Types> void g(Tuple<Types ...>); // #1template<class T1, class ... Types> void g(Tuple<T1, Types ...>); // #2template<class T1, class ... Types> void g(Tuple<T1, Types& ...>); // #3 g(Tuple<>()); // calls #1 g(Tuple<int, float>()); // calls #2 g(Tuple<int, float&>()); // calls #3 g(Tuple<int>()); // calls #3 — *end example*]
[119)](#footnote-119)[119)](#footnoteref-119)
Default arguments
are not considered to be arguments in this context; they only become arguments
after a function has been selected[.](#footnote-119.sentence-1)

View File

@@ -0,0 +1,540 @@
[temp.deduct.type]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.type)
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#type)
#### 13.10.3.6 Deducing template arguments from a type [temp.deduct.type]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8791)
Template arguments can be deduced in several different contexts, but
in each case a type that is specified in terms of template parameters
(call itP)
is compared with an actual type (call itA),
and an attempt is made to find template argument values (a type for a type
parameter, a value for a constant template parameter, or a template for a
template template parameter) that will makeP,
after substitution of the deduced values (call it the deducedA),
compatible withA[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8807)
In some cases, the deduction is done using a single set of typesP andA,
in other cases, there will be a set of corresponding typesP andA[.](#2.sentence-1)
Type deduction is done
independently for eachP/A pair, and the deduced template
argument values are then combined[.](#2.sentence-2)
If type deduction cannot be done
for anyP/A pair, or if for any pair the deduction leads to more than
one possible set of deduced values, or if different pairs yield
different deduced values, or if any template argument remains neither
deduced nor explicitly specified, template argument deduction fails[.](#2.sentence-3)
The type of a type parameter
is only deduced from an array bound
if it is not otherwise deduced[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8832)
A given typeP can be composed from a number of other
types, templates, and constant template argument values:
- [(3.1)](#3.1)
A function type includes the types of each of the function parameters,
the return type, and its exception specification[.](#3.1.sentence-1)
- [(3.2)](#3.2)
A pointer-to-member type includes the type of the class object pointed to
and the type of the member pointed to[.](#3.2.sentence-1)
- [(3.3)](#3.3)
A type that is a specialization of a class template (e.g.,A<int>)
includes the types, templates, and constant template argument values referenced by the
template argument list of the specialization[.](#3.3.sentence-1)
- [(3.4)](#3.4)
An array type includes the array element type and the value of the
array bound[.](#3.4.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8854)
In most cases, the types, templates, and constant template argument values that are used
to composeP participate in template argument deduction[.](#4.sentence-1)
That is,
they may be used to determine the value of a template argument, and
template argument deduction fails if
the value so determined is not consistent with the values determined
elsewhere[.](#4.sentence-2)
In certain contexts, however, the value does not
participate in type deduction, but instead uses the values of template
arguments that were either deduced elsewhere or explicitly specified[.](#4.sentence-3)
If a template parameter is used only in non-deduced contexts and is not
explicitly specified, template argument deduction fails[.](#4.sentence-4)
[*Note [1](#note-1)*:
Under [[temp.deduct.call]](temp.deduct.call "13.10.3.2Deducing template arguments from a function call"),
if P contains no template parameters that appear
in deduced contexts, no deduction is done, so P and A need not have the same form[.](#4.sentence-5)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8876)
The non-deduced contexts are:
- [(5.1)](#5.1)
The[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of a type that was specified using a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#5.1.sentence-1)
- [(5.2)](#5.2)
A [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") or a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]")[.](#5.2.sentence-1)
- [(5.3)](#5.3)
A [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")[.](#5.3.sentence-1)
- [(5.4)](#5.4)
The [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") of a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]")[.](#5.4.sentence-1)
- [(5.5)](#5.5)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") of a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")[.](#5.5.sentence-1)
- [(5.6)](#5.6)
A constant template argument or an array bound in which a subexpression
references a template parameter[.](#5.6.sentence-1)
- [(5.7)](#5.7)
A template parameter used in the parameter type of a function parameter that
has a default argument that is being used in the call for which argument
deduction is being done[.](#5.7.sentence-1)
- [(5.8)](#5.8)
A function parameter for which the associated argument is an
overload set such that one or more of the following apply:
* [(5.8.1)](#5.8.1)
functions whose associated constraints are satisfied and
that do not all have the same function type
match the function parameter type (resulting in an ambiguous deduction), or
* [(5.8.2)](#5.8.2)
no function whose associated constraints are satisfied
matches the function parameter type, or
* [(5.8.3)](#5.8.3)
the overload set supplied as an argument contains one or more function templates[.](#5.8.sentence-1)
[*Note [2](#note-2)*:
A particular function from the overload set is selected ([[over.over]](over.over "12.3Address of an overload set"))
after template argument deduction has succeeded ([[temp.over]](temp.over "13.10.4Overload resolution"))[.](#5.8.sentence-2)
— *end note*]
- [(5.9)](#5.9)
A function parameter for which the associated argument is an initializer
list ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")) but the parameter does not have
a type for which deduction from an initializer list is specified ([[temp.deduct.call]](temp.deduct.call "13.10.3.2Deducing template arguments from a function call"))[.](#5.9.sentence-1)
[*Example [1](#example-1)*: template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T — *end example*]
- [(5.10)](#5.10)
A function parameter pack that does not occur at the end of the[*parameter-declaration-list*](dcl.fct#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]")[.](#5.10.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8931)
When a type name is specified in a way that includes a non-deduced
context, all of the types that comprise that type name are also
non-deduced[.](#6.sentence-1)
However, a compound type can include both deduced and non-deduced types[.](#6.sentence-2)
[*Example [2](#example-2)*:
If a type is specified asA<T>::B<T2>,
bothT andT2 are non-deduced[.](#6.sentence-3)
Likewise, if a type is specified asA<I+J>::X<T>,I,J,
andT are non-deduced[.](#6.sentence-4)
If a type is specified asvoidf(typenameA<T>::B,A<T>),
theT inA<T>::B is non-deduced but
theT inA<T> is deduced[.](#6.sentence-5)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8968)
[*Example [3](#example-3)*:
Here is an example in which different parameter/argument pairs produce
inconsistent template argument deductions:template<class T> void f(T x, T y) { /* ... */ }struct A { /* ... */ };struct B : A { /* ... */ };void g(A a, B b) { f(a,b); // error: T deduced as both A and B f(b,a); // error: T deduced as both A and B f(a,a); // OK, T is A f(b,b); // OK, T is B}
Here is an example where two template arguments are deduced from a
single function parameter/argument pair[.](#7.sentence-2)
This can lead to conflicts
that cause type deduction to fail:template <class T, class U> void f(T (*)(T, U, U));
int g1(int, float, float);char g2(int, float, float);int g3(int, char, float);
void r() { f(g1); // OK, T is int and U is float f(g2); // error: T deduced as both char and int f(g3); // error: U deduced as both char and float}
Here is an example where the exception specification of a function type
is deduced:template<bool E> void f1(void (*)() noexcept(E));template<bool> struct A { };template<bool B> void f2(void (*)(A<B>) noexcept(B));
void g1();void g2() noexcept;void g3(A<true>);
void h() { f1(g1); // OK, E is false f1(g2); // OK, E is true f2(g3); // error: B deduced as both true and false}
Here is an example where a qualification conversion applies between the
argument type on the function call and the deduced template argument type:template<class T> void f(const T*) { }int* p;void s() { f(p); // f(const int*)}
Here is an example where the template argument is used to instantiate
a derived class type of the corresponding function parameter type:template <class T> struct B { };template <class T> struct D : public B<T> {};struct D2 : public B<int> {};template <class T> void f(B<T>&) {}void t() { D<int> d;
D2 d2;
f(d); // calls f(B<int>&) f(d2); // calls f(B<int>&)}
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9046)
A type template argument T,
a constant template argument i,
a template template argument TT denoting a class template or an alias template, or
a template template argument VV denoting a variable template or a concept
can be deduced ifP andA have one of the following forms:cvopt T
T* T& T&& Topt[iopt] Topt(Topt) noexcept(iopt) Topt Topt::* TTopt<T> TTopt<i> TTopt<TT> TTopt<VV> TTopt<> where
- [(8.1)](#8.1)
Topt represents a type or parameter-type-list that either
satisfies these rules recursively,
is a non-deduced context in P or A, or
is the same non-dependent type in P and A,
- [(8.2)](#8.2)
iopt represents an expression that either
is an i,
is value-dependent in P or A, or
has the same constant value in P and A,
- [(8.3)](#8.3)
TTopt represents either a class template or
a template template parameter, and
- [(8.4)](#8.4)
noexcept(iopt) represents an
exception specification ([[except.spec]](except.spec "14.5Exception specifications"))
in which the (possibly-implicit, see [[dcl.fct]](dcl.fct "9.3.4.6Functions"))[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")'s operand
satisfies the rules for an iopt above[.](#8.sentence-1)
[*Note [3](#note-3)*:
If a type matches such a form but contains noTs, is, or TTs, deduction is not possible[.](#8.sentence-2)
— *end note*]
Similarly,<X> represents template argument lists where
at least one argument contains an X, whereX is one of T, i, TT, or VV;
and<> represents template argument lists where no argument contains aT, an i, a TT, or a VV[.](#8.sentence-3)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9112)
If P has a form that contains<T>, <i>, <TT>, or <VV>,
then each argument Pi of the
respective template argument list of P is compared with the
corresponding argument Ai of the corresponding
template argument list of A[.](#9.sentence-1)
If the template argument list
of P contains a pack expansion that is not the last
template argument, the entire template argument list is a non-deduced
context[.](#9.sentence-2)
If Pi is a pack expansion, then the pattern
of Pi is compared with each remaining argument in the
template argument list of A[.](#9.sentence-3)
Each comparison deduces
template arguments for subsequent positions in the template parameter
packs expanded by Pi[.](#9.sentence-4)
During [partial ordering](temp.deduct.partial "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]"), if Ai was
originally a pack expansion:
- [(9.1)](#9.1)
if P does not contain a template argument corresponding toAi then Ai is ignored;
- [(9.2)](#9.2)
otherwise, if Pi is not a pack expansion, template argument
deduction fails[.](#9.sentence-5)
[*Example [4](#example-4)*: template<class T1, class... Z> class S; // #1template<class T1, class... Z> class S<T1, const Z&...> { }; // #2template<class T1, class T2> class S<T1, const T2&> { }; // #3 S<int, const int&> s; // both #2 and #3 match; #3 is more specializedtemplate<class T, class... U> struct A { }; // #1template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; // #2template<class T1, class T2> struct A<T1, T2> { }; // #3template struct A<int, int*>; // selects #2 — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9149)
Similarly, if P has a form that contains(T), then each parameter type Pi of the respective parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) ofP is compared with the corresponding parameter typeAi of the corresponding parameter-type-list
of A[.](#10.sentence-1)
If P and A are function types that originated from deduction when
taking the address of a function template ([[temp.deduct.funcaddr]](temp.deduct.funcaddr "13.10.3.3Deducing template arguments taking the address of a function template")) or when
deducing template arguments from a function declaration ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7Deducing template arguments from a function declaration"))
and Pi and Ai are parameters of the top-level
parameter-type-list of P and A, respectively,Pi is adjusted if it is a forwarding reference ([[temp.deduct.call]](temp.deduct.call "13.10.3.2Deducing template arguments from a function call"))
and Ai is an lvalue reference, in which case the type ofPi is changed to be the template parameter type (i.e., T&& is
changed to simply T)[.](#10.sentence-2)
[*Note [4](#note-4)*:
As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T,
causing T to be deduced as X&[.](#10.sentence-3)
— *end note*]
[*Example [5](#example-5)*: template <class T> void f(T&&);template <> void f(int&) { } // #1template <> void f(int&&) { } // #2void g(int i) { f(i); // calls f<int&>(int&), i.e., #1 f(0); // calls f<int>(int&&), i.e., #2} — *end example*]
If the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") corresponding to Pi is a function parameter pack,
then the type of its [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is compared with
each remaining parameter type in the parameter-type-list
of A[.](#10.sentence-4)
Each comparison deduces template arguments for
subsequent positions in the template parameter packs expanded by the
function parameter pack[.](#10.sentence-5)
During [partial ordering](temp.deduct.partial "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]"), if Ai was
originally a function parameter pack:
- [(10.1)](#10.1)
if P does not contain a function parameter type corresponding toAi then Ai is ignored;
- [(10.2)](#10.2)
otherwise, if Pi is not a function parameter pack, template
argument deduction fails[.](#10.sentence-6)
[*Example [6](#example-6)*: template<class T, class... U> void f(T*, U...) { } // #1template<class T> void f(T) { } // #2template void f(int*); // selects #1 — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9206)
These forms can be used in the same way asT is for further composition of types[.](#11.sentence-1)
[*Example [7](#example-7)*:
X<int> (*)(char[6]) is of the form[*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")<T> (*)(*type*[i]) which is a variant of*type* (*)(T) where type isX<int> andT ischar[6][.](#11.sentence-2)
— *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9230)
Template arguments cannot be deduced from function arguments involving
constructs other than the ones specified above[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9234)
When the value of the argument
corresponding to a constant template parameter P that is declared with a dependent type
is deduced from an expression,
the template parameters in the type of P are deduced from the type of the value[.](#13.sentence-1)
[*Example [8](#example-8)*: template<long n> struct A { };
template<typename T> struct C;template<typename T, T n> struct C<A<n>> {using Q = T;};
using R = long;using R = C<A<2>>::Q; // OK; T was deduced as long from the// template argument value in the type A<2> — *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9256)
The type of N in the type T[N] is std::size_t[.](#14.sentence-1)
[*Example [9](#example-9)*: template<typename T> struct S;template<typename T, T n> struct S<int[n]> {using Q = T;};
using V = decltype(sizeof 0);using V = S<int[42]>::Q; // OK; T was deduced as std::size_t from the type int[42] — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9270)
The type of B in the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")noexcept(B) of a function type is bool[.](#15.sentence-1)
[*Example [10](#example-10)*: template<bool> struct A { };template<auto> struct B;template<auto X, void (*F)() noexcept(X)> struct B<F> { A<X> ax;};void f_nothrow() noexcept;
B<f_nothrow> bn; // OK, type of X deduced as bool — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9285)
[*Example [11](#example-11)*: template<class T, T i> void f(int (&a)[i]);int v[10];void g() { f(v); // OK, T is std::size_t} — *end example*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9296)
[*Note [5](#note-5)*:
Except for reference and pointer types, a major array bound is not part of a
function parameter type and cannot be deduced from an argument:template<int i> void f1(int a[10][i]);template<int i> void f2(int a[i][20]);template<int i> void f3(int (&a)[i][20]);
void g() {int v[10][20];
f1(v); // OK, i deduced as 20 f1<20>(v); // OK f2(v); // error: cannot deduce template-argument i f2<10>(v); // OK f3(v); // OK, i deduced as 10}
— *end note*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9316)
[*Note [6](#note-6)*:
If, in the declaration of a function template with a constant
template parameter, the constant template parameter
is used in a subexpression in the function parameter list,
the expression is a non-deduced context as specified above[.](#18.sentence-1)
[*Example [12](#example-12)*: template <int i> class A { /* ... */ };template <int i> void g(A<i+1>);template <int i> void f(A<i>, A<i+1>);void k() { A<1> a1;
A<2> a2;
g(a1); // error: deduction fails for expression i+1 g<0>(a1); // OK f(a1, a2); // OK} — *end example*]
— *end note*]
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9338)
[*Note [7](#note-7)*:
Template parameters do not participate in template argument deduction if
they are used only in non-deduced contexts[.](#19.sentence-1)
For example,
template<int i, typename T> T deduce(typename A<T>::X x, // T is not deduced here T t, // but T is deduced heretypename B<i>::Y y); // i is not deduced here A<int> a;
B<77> b;
int x = deduce<77>(a.xm, 62, b.ym);// T deduced as int; a.xm must be convertible to A<int>::X// i is explicitly specified to be 77; b.ym must be convertible to B<77>::Y — *end note*]
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9358)
If P has a form that contains <i>, and
if the type of i differs from the type
of the corresponding template parameter
of the template named by the enclosing [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"), deduction fails[.](#20.sentence-1)
If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails[.](#20.sentence-2)[120](#footnote-120 "Although the template-argument corresponding to a template parameter of type bool can be deduced from an array bound, the resulting value will always be true because the array bound will be nonzero.")
If P has a form that includes noexcept(i) and
the type of i is not bool, deduction fails[.](#20.sentence-3)
[*Example [13](#example-13)*: template<int i> class A { /* ... */ };template<short s> void f(A<s>);void k1() { A<1> a;
f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK}template<const short cs> class B { };template<short s> void g(B<s>);void k2() { B<1> b;
g(b); // OK, cv-qualifiers are ignored on template parameter types} — *end example*]
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9396)
A[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") can be deduced from a function, pointer to function, or
pointer-to-member-function type[.](#21.sentence-1)
[*Example [14](#example-14)*: template<class T> void f(void(*)(T,int));template<class T> void foo(T,int);void g(int,int);void g(char,int);
void h(int,int,int);void h(char,int);int m() { f(&g); // error: ambiguous f(&h); // OK, void h(char,int) is a unique match f(&foo); // error: type deduction fails because foo is a template} — *end example*]
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9419)
A template[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") cannot be deduced from the type of a function default argument[.](#22.sentence-1)
[*Example [15](#example-15)*: template <class T> void f(T = 5, T = 7);void g() { f(1); // OK, calls f<int>(1,7) f(); // error: cannot deduce T f<int>(); // OK, calls f<int>(5,7)} — *end example*]
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9434)
The[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") corresponding to a template template parameter
is deduced from the type of the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") of a class template specialization used in the argument list of a function call[.](#23.sentence-1)
[*Example [16](#example-16)*: template <template <class T> class X> struct A { };template <template <class T> class X> void f(A<X>) { }template<class T> struct B { };
A<B> ab;
f(ab); // calls f(A<B>) — *end example*]
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9451)
[*Note [8](#note-8)*:
Template argument deduction involving parameter
packs ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")) can deduce zero or more arguments for
each parameter pack[.](#24.sentence-1)
— *end note*]
[*Example [17](#example-17)*: template<class> struct X { };template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { };template<class ... Types> struct Y { };template<class T, class ... Types> struct Y<T, Types& ...> { };
template<class ... Types> int f(void (*)(Types ...));void g(int, float);
X<int> x1; // uses primary template X<int(int, float, double)> x2; // uses partial specialization; ArgTypes contains float, double X<int(float, int)> x3; // uses primary template Y<> y1; // uses primary template; Types is empty Y<int&, float&, double&> y2; // uses partial specialization; T is int&, Types contains float, double Y<int, float, double> y3; // uses primary template; Types contains int, float, doubleint fv = f(g); // OK; Types contains int, float — *end example*]
[120)](#footnote-120)[120)](#footnoteref-120)
Although the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") corresponding to a template parameter of typebool can be deduced from an array bound, the resulting value will always betrue because the array bound will be nonzero[.](#footnote-120.sentence-1)

829
cppdraft/temp/dep.md Normal file
View File

@@ -0,0 +1,829 @@
[temp.dep]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep)
### 13.8.3 Dependent names [temp.dep]
#### [13.8.3.1](#general) General [[temp.dep.general]](temp.dep.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5268)
Inside a template, some constructs have semantics which may differ from one
instantiation to another[.](#general-1.sentence-1)
Such a construct[*depends*](#def:name,dependent "13.8.3.1General[temp.dep.general]") on the template parameters[.](#general-1.sentence-2)
In particular, types and expressions may depend on the type
and/or
value of
template parameters (as determined by the template arguments) and this determines
the context for name lookup for certain names[.](#general-1.sentence-3)
An expression may be[*type-dependent*](#def:expression,type-dependent "13.8.3.1General[temp.dep.general]") (that is, its type may depend on a template parameter) or[*value-dependent*](#def:expression,value-dependent "13.8.3.1General[temp.dep.general]") (that is, its value when evaluated as a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
may depend on a template parameter)
as described below[.](#general-1.sentence-4)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5288)
A [*dependent call*](#def:call,dependent "13.8.3.1General[temp.dep.general]") is an expression,
possibly formed as a non-member candidate for an operator ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions")),
of the form:
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
where the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") and
- [(2.1)](#general-2.1)
any of the expressions in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), or
- [(2.2)](#general-2.2)
any of the expressions
or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")*s* in the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is [type-dependent](#expr "13.8.3.3Type-dependent expressions[temp.dep.expr]"), or
- [(2.3)](#general-2.3)
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") in which any of the template arguments depends
on a template parameter[.](#general-2.sentence-1)
The component name of an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))
is dependent if
- [(2.4)](#general-2.4)
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") is dependent, or
- [(2.5)](#general-2.5)
it is operator= and
the current class is a templated entity, or
- [(2.6)](#general-2.6)
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") in a dependent call[.](#general-2.sentence-2)
[*Note [1](#general-note-1)*:
Such names
are looked up only at the point of the template instantiation ([[temp.point]](temp.point "13.8.4.1Point of instantiation"))
in both the context of the template definition and the
context of the point of instantiation ([[temp.dep.candidate]](temp.dep.candidate "13.8.4.2Candidate functions"))[.](#general-2.sentence-3)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5332)
[*Example [1](#general-example-1)*: template<class T> struct X : B<T> {typename T::A* pa; void f(B<T>* pb) {static int i = B<T>::i;
pb->j++; }};
The base class nameB<T>,
the type nameT::A,
the namesB<T>::i andpb->j explicitly depend on the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")[.](#general-3.sentence-1)
— *end example*]
#### [13.8.3.2](#type) Dependent types [[temp.dep.type]](temp.dep.type)
[1](#type-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5358)
A name or [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") refers to the[*current instantiation*](#def:current_instantiation "13.8.3.2Dependent types[temp.dep.type]") if it is
- [(1.1)](#type-1.1)
in the definition of a class template, a nested class of a class template,
a member of a class template, or a member of a nested class of a class template,
the [injected-class-name](class.pre#def:injected-class-name "11.1Preamble[class.pre]") of the class template or nested class,
- [(1.2)](#type-1.2)
in the definition of a primary class template
or a member of a primary class template, the name of the
class template followed by the template argument list of
its [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template arguments")) enclosed in<> (or an equivalent template alias specialization),
- [(1.3)](#type-1.3)
in the definition of a nested class of a class template,
the name of the nested class referenced as a member of the
current instantiation,
- [(1.4)](#type-1.4)
in the definition of a class template partial specialization
or a member of a class template partial specialization, the name of
the class template followed by a template argument list
equivalent to that of the partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"))
enclosed in <> (or an equivalent template alias specialization), or
- [(1.5)](#type-1.5)
in the definition of a templated function,
the name of a local class ([[class.local]](class.local "11.6Local class declarations"))[.](#type-1.sentence-1)
[2](#type-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5388)
A template argument that is equivalent to a template
parameter can be used in place of that
template parameter in a reference to the current instantiation[.](#type-2.sentence-1)
A template argument is equivalent to a type template parameter
if it denotes the same type[.](#type-2.sentence-2)
A template argument is equivalent to a constant template parameter
if it is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that names a variable
that is equivalent to the template parameter[.](#type-2.sentence-3)
A variable is equivalent to a template parameter if
- [(2.1)](#type-2.1)
it has the same type as the template parameter
(ignoring cv-qualification) and
- [(2.2)](#type-2.2)
its initializer consists of a single [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that names the template parameter or, recursively, such a variable[.](#type-2.sentence-4)
[*Note [1](#type-note-1)*:
Using a parenthesized variable name breaks the equivalence[.](#type-2.sentence-5)
— *end note*]
[*Example [1](#type-example-1)*: template <class T> class A { A* p1; // A is the current instantiation A<T>* p2; // A<T> is the current instantiation A<T*> p3; // A<T*> is not the current instantiation::A<T>* p4; // ::A<T> is the current instantiationclass B { B* p1; // B is the current instantiation A<T>::B* p2; // A<T>::B is the current instantiationtypename A<T*>::B* p3; // A<T*>::B is not the current instantiation};};
template <class T> class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A<T>* p2; // A<T> is not the current instantiation};
template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; // refers to the current instantiation B<T2, T1, I>* b2; // not the current instantiationtypedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; static const long my_I4 = I; static const int my_I5 = (I);
B<my_T1, T2, my_I>* b3; // refers to the current instantiation B<my_T1, T2, my_I2>* b4; // not the current instantiation B<my_T1, T2, my_I3>* b5; // refers to the current instantiation B<my_T1, T2, my_I4>* b6; // not the current instantiation B<my_T1, T2, my_I5>* b7; // not the current instantiation}; — *end example*]
[3](#type-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5446)
A [*dependent base class*](#def:base_class,dependent "13.8.3.2Dependent types[temp.dep.type]") is a base class that is a dependent type and is
not the current instantiation[.](#type-3.sentence-1)
[*Note [2](#type-note-2)*:
A base class can be the current instantiation in the case of a nested class
naming an enclosing class as a base[.](#type-3.sentence-2)
[*Example [2](#type-example-2)*: template<class T> struct A {typedef int M; struct B {typedef void M; struct C; };};
template<class T> struct A<T>::B::C : A<T> { M m; // OK, A<T>::M}; — *end example*]
— *end note*]
[4](#type-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5470)
A qualified ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup")) or unqualified name is a[*member of the current instantiation*](#def:current_instantiation,member_of_the "13.8.3.2Dependent types[temp.dep.type]") if
- [(4.1)](#type-4.1)
its lookup context, if it is a qualified name,
is the current instantiation, and
- [(4.2)](#type-4.2)
lookup for it finds any member of a class that is the current instantiation
[*Example [3](#type-example-3)*: template <class T> class A {static const int i = 5; int n1[i]; // i refers to a member of the current instantiationint n2[A::i]; // A::i refers to a member of the current instantiationint n3[A<T>::i]; // A<T>::i refers to a member of the current instantiationint f();};
template <class T> int A<T>::f() {return i; // i refers to a member of the current instantiation} — *end example*]
A qualified or unqualified name names a [*dependent member of the current instantiation*](#def:current_instantiation,dependent_member_of_the "13.8.3.2Dependent types[temp.dep.type]") if it is a
member of the current instantiation that, when looked up, refers to at least
one member declaration
(including a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") whose terminal name is dependent)
of a class that is the current instantiation[.](#type-4.sentence-2)
[5](#type-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5505)
A qualified name ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup")) is dependent if
- [(5.1)](#type-5.1)
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") is dependent, or
- [(5.2)](#type-5.2)
its lookup context is dependent and is not the current instantiation, or
- [(5.3)](#type-5.3)
its lookup context is the current instantiation and
it is operator=,[117](#footnote-117 "Every instantiation of a class template declares a different set of assignment operators.") or
- [(5.4)](#type-5.4)
its lookup context is the current instantiation and
has at least one dependent base class, and
qualified name lookup for the name finds nothing ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup"))[.](#type-5.sentence-1)
[*Example [4](#type-example-4)*: struct A {using B = int;
A f();};struct C : A {};template<class T>void g(T t) {decltype(t.A::f())::B i; // error: typename needed to interpret B as a type}template void g(C); // …even though A is ::A here — *end example*]
[6](#type-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5541)
If, for a given set of template arguments, a specialization of a template is
instantiated that refers to a member of the current instantiation with a
qualified name, the name is looked up in the
template instantiation context[.](#type-6.sentence-1)
If the result of this lookup differs from the
result of name lookup in the template definition context, name lookup is
ambiguous[.](#type-6.sentence-2)
[*Example [5](#type-example-5)*: struct A {int m;};
struct B {int m;};
template<typename T>struct C : A, T {int f() { return this->m; } // finds A::m in the template definition contextint g() { return m; } // finds A::m in the template definition context};
template int C<B>::f(); // error: finds both A::m and B::mtemplate int C<B>::g(); // OK, transformation to class member access syntax// does not occur in the template definition context; see [[expr.prim.id.general]](expr.prim.id.general "7.5.5.1General") — *end example*]
[7](#type-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5570)
An initializer is dependent if
any constituent expression ([[intro.execution]](intro.execution "6.10.1Sequential execution")) of the initializer
is type-dependent[.](#type-7.sentence-1)
A placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1General")) is dependent if
it designates a type deduced from a dependent initializer[.](#type-7.sentence-2)
[8](#type-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5577)
A placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))
is dependent if
- [(8.1)](#type-8.1)
it has a dependent initializer, or
- [(8.2)](#type-8.2)
it refers to an alias template
that is a member of the current instantiation and
whose [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") is dependent after
class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction"))
and substitution ([[temp.alias]](temp.alias "13.7.8Alias templates"))[.](#type-8.sentence-1)
[9](#type-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5591)
[*Example [6](#type-example-6)*: template<class T, class V>struct S { S(T); };
template<class U>struct A {template<class T> using X = S<T, U>; template<class T> using Y = S<T, int>; void f() {new X(1); // dependentnew Y(1); // not dependent}}; — *end example*]
[10](#type-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5609)
A type is dependent if it is
- [(10.1)](#type-10.1)
a template parameter,
- [(10.2)](#type-10.2)
denoted by a dependent (qualified) name,
- [(10.3)](#type-10.3)
a nested class or enumeration that is a direct member of
a class that is the current instantiation,
- [(10.4)](#type-10.4)
a cv-qualified type where the cv-unqualified type is dependent,
- [(10.5)](#type-10.5)
a compound type constructed from any dependent type,
- [(10.6)](#type-10.6)
an array type whose element type is dependent or whose
bound (if any) is value-dependent,
- [(10.7)](#type-10.7)
a function type whose parameters include one or more function parameter packs,
- [(10.8)](#type-10.8)
a function type whose exception specification is value-dependent,
- [(10.9)](#type-10.9)
denoted by a dependent placeholder type,
- [(10.10)](#type-10.10)
denoted by a dependent placeholder for a deduced class type,
- [(10.11)](#type-10.11)
denoted by a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") in which either the template name is a template parameter or any of the
template arguments is dependent ([[temp.dep.temp]](#temp "13.8.3.7Dependent template arguments")),[118](#footnote-118 "This includes an injected-class-name ([class.pre]) of a class template used without a template-argument-list.")
- [(10.12)](#type-10.12)
a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]"),
- [(10.13)](#type-10.13)
denoted by decltype([*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")),
where [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is [type-dependent](#expr "13.8.3.3Type-dependent expressions[temp.dep.expr]"), or
- [(10.14)](#type-10.14)
denoted by a [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") in which either
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5Dependent splice specifiers"))[.](#type-10.sentence-1)
[11](#type-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5651)
[*Note [3](#type-note-3)*:
Because typedefs do not introduce new types, but
instead simply refer to other types, a name that refers to a
typedef that is a member of the current instantiation is dependent
only if the type referred to is dependent[.](#type-11.sentence-1)
— *end note*]
[117)](#footnote-117)[117)](#footnoteref-117)
Every instantiation of a class template declares
a different set of assignment operators[.](#footnote-117.sentence-1)
[118)](#footnote-118)[118)](#footnoteref-118)
This includes an injected-class-name ([[class.pre]](class.pre "11.1Preamble")) of a class template
used without a [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")[.](#footnote-118.sentence-1)
#### [13.8.3.3](#expr) Type-dependent expressions [[temp.dep.expr]](temp.dep.expr)
[1](#expr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5661)
Except as described below, an expression is type-dependent if any
subexpression is type-dependent[.](#expr-1.sentence-1)
[2](#expr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5665)
this is type-dependent if the current class ([[expr.prim.this]](expr.prim.this "7.5.3This")) is
dependent ([[temp.dep.type]](#type "13.8.3.2Dependent types"))[.](#expr-2.sentence-1)
[3](#expr-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5670)
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is type-dependent
if it is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") that is not a concept-id and is dependent;
or if its terminal name is
- [(3.1)](#expr-3.1)
associated by name lookup with one or more declarations
declared with a dependent type,
- [(3.2)](#expr-3.2)
associated by name lookup with
a constant template parameter
declared with a type
that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")),
- [(3.3)](#expr-3.3)
associated by name lookup with
a variable declared with a type that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
where the initializer is type-dependent,
- [(3.4)](#expr-3.4)
associated by name lookup with one or more
declarations of member functions of a class that is the current instantiation
declared with a return type that contains a placeholder type,
- [(3.5)](#expr-3.5)
associated by name lookup with
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")) whose[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is type-dependent,
- [(3.6)](#expr-3.6)
associated by name lookup with a pack,
[*Example [1](#expr-example-1)*: struct C { };
void g(...); // #1template <typename T>void f() { C arr[1]; auto [...e] = arr;
g(e...); // calls #2}void g(C); // #2int main() { f<int>();} — *end example*]
- [(3.7)](#expr-3.7)
associated by name lookup with
an entity captured by copy ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures"))
in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") that has an explicit object parameter whose type is dependent ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
- [(3.8)](#expr-3.8)
the[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")__func__ ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")), where any enclosing function is a
template, a member of a class template, or a generic lambda,
- [(3.9)](#expr-3.9)
associated by name lookup
with a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")) of a function
whose return type is dependent,
- [(3.10)](#expr-3.10)
a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") that specifies a dependent type,
- [(3.11)](#expr-3.11)
a name N introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") of an expansion statement S if the type specified for N contains a placeholder type and either
* [(3.11.1)](#expr-3.11.1)
the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") of S is type-dependent or
* [(3.11.2)](#expr-3.11.2)
S is not an iterating expansion statement, or
- [(3.12)](#expr-3.12)
dependent
or if it names a dependent member of the current instantiation that is a static
data member of type
“array of unknown bound of T” for some T ([[temp.static]](temp.static "13.7.2.5Static data members of class templates"))[.](#expr-3.sentence-1)
Expressions of the following forms are type-dependent only if the type
specified by the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]"),[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]"),
or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") is dependent, even if any subexpression is type-dependent:
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8New[expr.new]")opt [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")opt
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8New[expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")opt
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[4](#expr-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5769)
Expressions of the following forms are never type-dependent (because the type
of the expression cannot be dependent):
[*literal*](lex.literal.kinds#nt:literal "5.13.1Kinds of literals[lex.literal.kinds]")
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
typeid ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
throw [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")opt
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
[*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")
[*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")
[*Note [1](#expr-note-1)*:
For the standard library macro offsetof,
see [[support.types]](support.types "17.2Common definitions")[.](#expr-4.sentence-2)
— *end note*]
[5](#expr-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5793)
A [class member access expression](expr.ref "7.6.1.5Class member access[expr.ref]") is
type-dependent if
the terminal name of its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"), if any, is dependent or
the expression refers to a member of the current instantiation and
the type of the referenced member is dependent[.](#expr-5.sentence-1)
[*Note [2](#expr-note-2)*:
In an expression of the formx.y orxp->y the type of the expression is usually the type of the membery of the class ofx (or the class pointed to byxp)[.](#expr-5.sentence-2)
However, ifx orxp refers to a dependent type that is not the current instantiation,
the type ofy is always dependent[.](#expr-5.sentence-3)
— *end note*]
[6](#expr-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5820)
A [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") is type-dependent if any element is
type-dependent or is a pack expansion[.](#expr-6.sentence-1)
[7](#expr-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5824)
A [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]") is type-dependent[.](#expr-7.sentence-1)
[8](#expr-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5827)
A [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") is type-dependent
if its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is type-dependent[.](#expr-8.sentence-1)
[9](#expr-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5831)
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") is type-dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5Dependent splice specifiers"))[.](#expr-9.sentence-1)
#### [13.8.3.4](#constexpr) Value-dependent expressions [[temp.dep.constexpr]](temp.dep.constexpr)
[1](#constexpr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5839)
Except as described below, an expression used in a context where a
constant expression is required is value-dependent if any
subexpression is value-dependent[.](#constexpr-1.sentence-1)
[2](#constexpr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5844)
An[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is value-dependent if
- [(2.1)](#constexpr-2.1)
it is a concept-id and
its [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") is dependent or
any of its arguments are dependent ([[temp.dep.temp]](#temp "13.8.3.7Dependent template arguments")),
- [(2.2)](#constexpr-2.2)
it is type-dependent,
- [(2.3)](#constexpr-2.3)
it is the name of a constant template parameter,
- [(2.4)](#constexpr-2.4)
it is a name introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements")),
- [(2.5)](#constexpr-2.5)
it names a static data member that is a dependent member of the current
instantiation and is not initialized in a [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]"),
- [(2.6)](#constexpr-2.6)
it names a static member function that is a dependent member of the current
instantiation, or
- [(2.7)](#constexpr-2.7)
it names a potentially-constant variable ([[expr.const]](expr.const "7.7Constant expressions"))
that is initialized with an expression that is value-dependent[.](#constexpr-2.sentence-1)
Expressions of the following form are value-dependent if the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]") or [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is type-dependent or the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") is dependent:
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
typeid ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
[*Note [1](#constexpr-note-1)*:
For the standard library macro offsetof,
see [[support.types]](support.types "17.2Common definitions")[.](#constexpr-2.sentence-3)
— *end note*]
[3](#constexpr-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5889)
Expressions of the following form are value-dependent if either the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]"), or[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") is dependent or the[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") or[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") is value-dependent or
any [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is value-dependent or
any [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") is value-dependent:
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[4](#constexpr-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5915)
Expressions of the following form are value-dependent:
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") )
[*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]")
unless the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is a structured binding pack
whose initializer is not dependent[.](#constexpr-4.sentence-1)
[5](#constexpr-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5924)
A [*noexcept-expression*](expr.unary.noexcept#nt:noexcept-expression "7.6.2.7noexcept operator[expr.unary.noexcept]") ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7noexcept operator"))
is value-dependent if
its [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") involves a template parameter[.](#constexpr-5.sentence-1)
[6](#constexpr-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5929)
An expression of the form &[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") names a dependent member of the current
instantiation is value-dependent[.](#constexpr-6.sentence-1)
An expression of the form &[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") is also value-dependent if evaluating [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") as a [core constant expression](expr.const#def:expression,core_constant "7.7Constant expressions[expr.const]") succeeds and
the result of the evaluation refers to a templated entity
that is an object with static or thread storage duration or a member function[.](#constexpr-6.sentence-2)
[7](#constexpr-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5939)
A [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") is value-dependent if
- [(7.1)](#constexpr-7.1)
it is of the form ^^[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") and
the [*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
* [(7.1.1)](#constexpr-7.1.1)
is a dependent qualified name,
* [(7.1.2)](#constexpr-7.1.2)
is a dependent [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]"),
* [(7.1.3)](#constexpr-7.1.3)
is the name of a template parameter, or
* [(7.1.4)](#constexpr-7.1.4)
names a dependent member of the current instantiation ([[temp.dep.type]](#type "13.8.3.2Dependent types")),
- [(7.2)](#constexpr-7.2)
it is of the form ^^[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") and
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") denotes a dependent type, or
- [(7.3)](#constexpr-7.3)
it is of the form ^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") and
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is value-dependent[.](#constexpr-7.sentence-1)
[8](#constexpr-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5959)
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") is value-dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5Dependent splice specifiers"))[.](#constexpr-8.sentence-1)
#### [13.8.3.5](#splice) Dependent splice specifiers [[temp.dep.splice]](temp.dep.splice)
[1](#splice-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5967)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") is dependent
if its converted [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") is value-dependent[.](#splice-1.sentence-1)
A [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") is dependent or
if any of its template arguments are dependent[.](#splice-1.sentence-2)
A [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") is dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent[.](#splice-1.sentence-3)
[2](#splice-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5977)
[*Example [1](#splice-example-1)*: template<auto T, auto NS>void fn() {using a = [:T:]<1>; // [:T:]<1> is dependent because [:T:] is dependentstatic_assert([:NS:]::template TCls<1>::v == a::v); // [:NS:] is dependent}namespace N {template <auto V> struct TCls { static constexpr int v = V; };}int main() { fn<^^N::TCls, ^^N>();} — *end example*]
[3](#splice-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5996)
[*Example [2](#splice-example-2)*: template<template<class> class X>struct S {[:^^X:]<int, float> m;};
template<class> struct V1 {};template<class, class = int> struct V2 {};
S<V1> s1; // error: V1<int, float> has too many template arguments S<V2> s2; // OK — *end example*]
#### [13.8.3.6](#namespace) Dependent namespaces [[temp.dep.namespace]](temp.dep.namespace)
[1](#namespace-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6014)
A namespace alias is dependent
if it is introduced by a [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3Namespace alias[namespace.alias]") whose [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3Namespace alias[namespace.alias]") (if any) is
a dependent qualified name or
whose [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") (if any) is dependent[.](#namespace-1.sentence-1)
A [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]") is dependent
if it names a dependent namespace alias[.](#namespace-1.sentence-2)
[2](#namespace-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6023)
[*Example [1](#namespace-example-1)*: template<std::meta::info R>int fn() {namespace Alias = [:R:]; // [:R:] is dependentreturn typename Alias::T{}; // Alias is dependent}namespace NS {using T = int;}int a = fn<^^NS>(); — *end example*]
#### [13.8.3.7](#temp) Dependent template arguments [[temp.dep.temp]](temp.dep.temp)
[1](#temp-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6042)
A type[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if the type it specifies is dependent[.](#temp-1.sentence-1)
[2](#temp-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6047)
A constant[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if its type is dependent or the constant
expression it specifies is value-dependent[.](#temp-2.sentence-1)
[3](#temp-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6053)
Furthermore, a constant[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if the corresponding constant template parameter
is of reference or pointer type and the [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") designates or points to a member of the current instantiation or a member of
a dependent type[.](#temp-3.sentence-1)
[4](#temp-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6061)
A template argument is also dependent if it is a pack expansion[.](#temp-4.sentence-1)
[5](#temp-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6065)
A template template parameter is dependent if
it names a template parameter or
its terminal name is dependent[.](#temp-5.sentence-1)

View File

@@ -0,0 +1,82 @@
[temp.dep.candidate]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.candidate)
### 13.8.4 Dependent name resolution [[temp.dep.res]](temp.dep.res#temp.dep.candidate)
#### 13.8.4.2 Candidate functions [temp.dep.candidate]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6171)
If a dependent call ([[temp.dep]](temp.dep "13.8.3Dependent names")) would be ill-formed or
would find a better match had the lookup for its dependent name
considered all the function declarations with external linkage
introduced in the associated namespaces in all translation units,
not just considering those declarations found in the template definition and
template instantiation contexts ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup")),
then the program is ill-formed, no diagnostic required[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6181)
[*Example [1](#example-1)*:
Source file "X.h":namespace Q {struct X { };}
Source file "G.h":namespace Q {void g_impl(X, X);}
Module interface unit of M1:module;#include "X.h"#include "G.h"export module M1;export template<typename T>void g(T t) { g_impl(t, Q::X{ }); // ADL in definition context finds Q::g_impl, g_impl not discarded}
Module interface unit of M2:module;#include "X.h"export module M2;import M1;void h(Q::X x) { g(x); // OK} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6217)
[*Example [2](#example-2)*:
Module interface unit of Std:export module Std;export template<typename Iter>void indirect_swap(Iter lhs, Iter rhs){ swap(*lhs, *rhs); // swap not found by unqualified lookup, can be found only via ADL}
Module interface unit of M:export module M;import Std;
struct S { /* ...*/ };void swap(S&, S&); // #1void f(S* p, S* q){ indirect_swap(p, q); // finds #1 via ADL in instantiation context} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6242)
[*Example [3](#example-3)*:
Source file "X.h":struct X { /* ... */ };
X operator+(X, X);
Module interface unit of F:export module F;export template<typename T>void f(T t) { t + t;}
Module interface unit of M:module;#include "X.h"export module M;import F;void g(X x) { f(x); // OK, instantiates f from F,// operator+ is visible in instantiation context} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6269)
[*Example [4](#example-4)*:
Module interface unit of A:export module A;export template<typename T>void f(T t) { cat(t, t); // #1 dog(t, t); // #2}
Module interface unit of B:export module B;import A;export template<typename T, typename U>void g(T t, U u) { f(t);}
Source file "foo.h", not an importable header:struct foo {friend int cat(foo, foo);};int dog(foo, foo);
Module interface unit of C1:module;#include "foo.h" // dog not referenced, discardedexport module C1;import B;export template<typename T>void h(T t) { g(foo{ }, t);}
Translation unit:import C1;void i() { h(0); // error: dog not found at #2}
Importable header "bar.h":struct bar {friend int cat(bar, bar);};int dog(bar, bar);
Module interface unit of C2:module;#include "bar.h" // imports header unit "bar.h"export module C2;import B;export template<typename T>void j(T t) { g(bar{ }, t);}
Translation unit:import C2;void k() { j(0); // OK, dog found in instantiation context:// visible at end of module interface unit of C2} — *end example*]

View File

@@ -0,0 +1,163 @@
[temp.dep.constexpr]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.constexpr)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#constexpr)
#### 13.8.3.4 Value-dependent expressions [temp.dep.constexpr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5839)
Except as described below, an expression used in a context where a
constant expression is required is value-dependent if any
subexpression is value-dependent[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5844)
An[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is value-dependent if
- [(2.1)](#2.1)
it is a concept-id and
its [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") is dependent or
any of its arguments are dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7Dependent template arguments")),
- [(2.2)](#2.2)
it is type-dependent,
- [(2.3)](#2.3)
it is the name of a constant template parameter,
- [(2.4)](#2.4)
it is a name introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements")),
- [(2.5)](#2.5)
it names a static data member that is a dependent member of the current
instantiation and is not initialized in a [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]"),
- [(2.6)](#2.6)
it names a static member function that is a dependent member of the current
instantiation, or
- [(2.7)](#2.7)
it names a potentially-constant variable ([[expr.const]](expr.const "7.7Constant expressions"))
that is initialized with an expression that is value-dependent[.](#2.sentence-1)
Expressions of the following form are value-dependent if the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]") or [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is type-dependent or the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") is dependent:
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
typeid ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
[*Note [1](#note-1)*:
For the standard library macro offsetof,
see [[support.types]](support.types "17.2Common definitions")[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5889)
Expressions of the following form are value-dependent if either the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]"), or[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") is dependent or the[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") or[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") is value-dependent or
any [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is value-dependent or
any [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") is value-dependent:
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5915)
Expressions of the following form are value-dependent:
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") )
[*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]")
unless the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is a structured binding pack
whose initializer is not dependent[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5924)
A [*noexcept-expression*](expr.unary.noexcept#nt:noexcept-expression "7.6.2.7noexcept operator[expr.unary.noexcept]") ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7noexcept operator"))
is value-dependent if
its [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") involves a template parameter[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5929)
An expression of the form &[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") names a dependent member of the current
instantiation is value-dependent[.](#6.sentence-1)
An expression of the form &[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") is also value-dependent if evaluating [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") as a [core constant expression](expr.const#def:expression,core_constant "7.7Constant expressions[expr.const]") succeeds and
the result of the evaluation refers to a templated entity
that is an object with static or thread storage duration or a member function[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5939)
A [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") is value-dependent if
- [(7.1)](#7.1)
it is of the form ^^[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") and
the [*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
* [(7.1.1)](#7.1.1)
is a dependent qualified name,
* [(7.1.2)](#7.1.2)
is a dependent [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]"),
* [(7.1.3)](#7.1.3)
is the name of a template parameter, or
* [(7.1.4)](#7.1.4)
names a dependent member of the current instantiation ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types")),
- [(7.2)](#7.2)
it is of the form ^^[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") and
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") denotes a dependent type, or
- [(7.3)](#7.3)
it is of the form ^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") and
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is value-dependent[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5959)
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") is value-dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5Dependent splice specifiers"))[.](#8.sentence-1)

198
cppdraft/temp/dep/expr.md Normal file
View File

@@ -0,0 +1,198 @@
[temp.dep.expr]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.expr)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#expr)
#### 13.8.3.3 Type-dependent expressions [temp.dep.expr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5661)
Except as described below, an expression is type-dependent if any
subexpression is type-dependent[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5665)
this is type-dependent if the current class ([[expr.prim.this]](expr.prim.this "7.5.3This")) is
dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5670)
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is type-dependent
if it is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") that is not a concept-id and is dependent;
or if its terminal name is
- [(3.1)](#3.1)
associated by name lookup with one or more declarations
declared with a dependent type,
- [(3.2)](#3.2)
associated by name lookup with
a constant template parameter
declared with a type
that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")),
- [(3.3)](#3.3)
associated by name lookup with
a variable declared with a type that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))
where the initializer is type-dependent,
- [(3.4)](#3.4)
associated by name lookup with one or more
declarations of member functions of a class that is the current instantiation
declared with a return type that contains a placeholder type,
- [(3.5)](#3.5)
associated by name lookup with
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")) whose[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is type-dependent,
- [(3.6)](#3.6)
associated by name lookup with a pack,
[*Example [1](#example-1)*: struct C { };
void g(...); // #1template <typename T>void f() { C arr[1]; auto [...e] = arr;
g(e...); // calls #2}void g(C); // #2int main() { f<int>();} — *end example*]
- [(3.7)](#3.7)
associated by name lookup with
an entity captured by copy ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures"))
in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") that has an explicit object parameter whose type is dependent ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
- [(3.8)](#3.8)
the[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")__func__ ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")), where any enclosing function is a
template, a member of a class template, or a generic lambda,
- [(3.9)](#3.9)
associated by name lookup
with a result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")) of a function
whose return type is dependent,
- [(3.10)](#3.10)
a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") that specifies a dependent type,
- [(3.11)](#3.11)
a name N introduced by the [*for-range-declaration*](stmt.pre#nt:for-range-declaration "8.1Preamble[stmt.pre]") of an expansion statement S if the type specified for N contains a placeholder type and either
* [(3.11.1)](#3.11.1)
the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") of S is type-dependent or
* [(3.11.2)](#3.11.2)
S is not an iterating expansion statement, or
- [(3.12)](#3.12)
dependent
or if it names a dependent member of the current instantiation that is a static
data member of type
“array of unknown bound of T” for some T ([[temp.static]](temp.static "13.7.2.5Static data members of class templates"))[.](#3.sentence-1)
Expressions of the following forms are type-dependent only if the type
specified by the[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]"),[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]"),
or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") is dependent, even if any subexpression is type-dependent:
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8New[expr.new]")opt [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")opt
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8New[expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")opt
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5769)
Expressions of the following forms are never type-dependent (because the type
of the expression cannot be dependent):
[*literal*](lex.literal.kinds#nt:literal "5.13.1Kinds of literals[lex.literal.kinds]")
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]")
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") )
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
typeid ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") )
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]")
throw [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")opt
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
[*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]")
[*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]")
[*Note [1](#note-1)*:
For the standard library macro offsetof,
see [[support.types]](support.types "17.2Common definitions")[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5793)
A [class member access expression](expr.ref "7.6.1.5Class member access[expr.ref]") is
type-dependent if
the terminal name of its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"), if any, is dependent or
the expression refers to a member of the current instantiation and
the type of the referenced member is dependent[.](#5.sentence-1)
[*Note [2](#note-2)*:
In an expression of the formx.y orxp->y the type of the expression is usually the type of the membery of the class ofx (or the class pointed to byxp)[.](#5.sentence-2)
However, ifx orxp refers to a dependent type that is not the current instantiation,
the type ofy is always dependent[.](#5.sentence-3)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5820)
A [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") is type-dependent if any element is
type-dependent or is a pack expansion[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5824)
A [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]") is type-dependent[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5827)
A [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") is type-dependent
if its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is type-dependent[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5831)
A [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") is type-dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5Dependent splice specifiers"))[.](#9.sentence-1)

View File

@@ -0,0 +1,94 @@
[temp.dep.general]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.general)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#general)
#### 13.8.3.1 General [temp.dep.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5268)
Inside a template, some constructs have semantics which may differ from one
instantiation to another[.](#1.sentence-1)
Such a construct[*depends*](#def:name,dependent "13.8.3.1General[temp.dep.general]") on the template parameters[.](#1.sentence-2)
In particular, types and expressions may depend on the type
and/or
value of
template parameters (as determined by the template arguments) and this determines
the context for name lookup for certain names[.](#1.sentence-3)
An expression may be[*type-dependent*](#def:expression,type-dependent "13.8.3.1General[temp.dep.general]") (that is, its type may depend on a template parameter) or[*value-dependent*](#def:expression,value-dependent "13.8.3.1General[temp.dep.general]") (that is, its value when evaluated as a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
may depend on a template parameter)
as described below[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5288)
A [*dependent call*](#def:call,dependent "13.8.3.1General[temp.dep.general]") is an expression,
possibly formed as a non-member candidate for an operator ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions")),
of the form:
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
where the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") and
- [(2.1)](#2.1)
any of the expressions in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), or
- [(2.2)](#2.2)
any of the expressions
or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")*s* in the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is [type-dependent](temp.dep.expr "13.8.3.3Type-dependent expressions[temp.dep.expr]"), or
- [(2.3)](#2.3)
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") in which any of the template arguments depends
on a template parameter[.](#2.sentence-1)
The component name of an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))
is dependent if
- [(2.4)](#2.4)
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") is dependent, or
- [(2.5)](#2.5)
it is operator= and
the current class is a templated entity, or
- [(2.6)](#2.6)
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1General[expr.post.general]") in a dependent call[.](#2.sentence-2)
[*Note [1](#note-1)*:
Such names
are looked up only at the point of the template instantiation ([[temp.point]](temp.point "13.8.4.1Point of instantiation"))
in both the context of the template definition and the
context of the point of instantiation ([[temp.dep.candidate]](temp.dep.candidate "13.8.4.2Candidate functions"))[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5332)
[*Example [1](#example-1)*: template<class T> struct X : B<T> {typename T::A* pa; void f(B<T>* pb) {static int i = B<T>::i;
pb->j++; }};
The base class nameB<T>,
the type nameT::A,
the namesB<T>::i andpb->j explicitly depend on the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")[.](#3.sentence-1)
— *end example*]

View File

@@ -0,0 +1,27 @@
[temp.dep.namespace]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.namespace)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#namespace)
#### 13.8.3.6 Dependent namespaces [temp.dep.namespace]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6014)
A namespace alias is dependent
if it is introduced by a [*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3Namespace alias[namespace.alias]") whose [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3Namespace alias[namespace.alias]") (if any) is
a dependent qualified name or
whose [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") (if any) is dependent[.](#1.sentence-1)
A [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[namespace.def.general]") is dependent
if it names a dependent namespace alias[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6023)
[*Example [1](#example-1)*: template<std::meta::info R>int fn() {namespace Alias = [:R:]; // [:R:] is dependentreturn typename Alias::T{}; // Alias is dependent}namespace NS {using T = int;}int a = fn<^^NS>(); — *end example*]

206
cppdraft/temp/dep/res.md Normal file
View File

@@ -0,0 +1,206 @@
[temp.dep.res]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.res)
### 13.8.4 Dependent name resolution [temp.dep.res]
#### [13.8.4.1](#temp.point) Point of instantiation [[temp.point]](temp.point)
[1](#temp.point-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6073)
For a function template specialization, a member function template
specialization, or a specialization for a member function or static data member
of a class template,
if the specialization is implicitly instantiated because it is referenced
from within another template specialization and
the context from which it is referenced depends on a template parameter,
the point of instantiation of the specialization is the point of instantiation
of the enclosing specialization[.](#temp.point-1.sentence-1)
Otherwise, the point of instantiation for such a specialization immediately
follows the namespace scope declaration
or definition that refers to the specialization[.](#temp.point-1.sentence-2)
[2](#temp.point-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6087)
If a function template or member function of a class template is called
in a way which uses the definition of a default argument of that function
template or member function,
the point of instantiation of the default argument is the point of
instantiation of the function template or member function specialization[.](#temp.point-2.sentence-1)
[3](#temp.point-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6094)
For a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") of a function template
specialization or specialization of a member function of a class template, if
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") is implicitly instantiated because
it is needed by another template specialization and the context that requires
it depends on a template parameter, the point of instantiation of the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") is the point of instantiation of the
specialization that requires it[.](#temp.point-3.sentence-1)
Otherwise, the point of instantiation for such
a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") immediately follows the namespace
scope declaration or definition that requires the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")[.](#temp.point-3.sentence-2)
[4](#temp.point-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6106)
For a class template specialization, a class member template specialization,
or a specialization for a class member of a class template,
if the specialization is implicitly instantiated because it is referenced
from within another template specialization,
if the context from which the specialization is referenced depends on a
template parameter,
and if the specialization is not instantiated previous to the instantiation of
the enclosing template,
the point of instantiation is immediately before the point of instantiation of
the enclosing template[.](#temp.point-4.sentence-1)
Otherwise, the point of instantiation for such a specialization immediately
precedes the namespace scope declaration
or definition that refers to the specialization[.](#temp.point-4.sentence-2)
[5](#temp.point-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6121)
If a virtual function is implicitly instantiated, its point of instantiation
is immediately following the point of instantiation of its enclosing class
template specialization[.](#temp.point-5.sentence-1)
[6](#temp.point-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6126)
An explicit instantiation definition is an instantiation
point for the specialization or specializations specified by the explicit
instantiation[.](#temp.point-6.sentence-1)
[7](#temp.point-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6131)
A specialization for a function template, a member function template,
or of a member function or static data member of a class template may have
multiple points of instantiations within a translation unit, and in addition
to the points of instantiation described above,
- [(7.1)](#temp.point-7.1)
for any such
specialization that has a point of instantiation within the[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1Preamble[dcl.pre]") of the[*translation-unit*](basic.link#nt:translation-unit "6.7Program and linkage[basic.link]"),
prior to the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]") (if any),
the point after the [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1Preamble[dcl.pre]") of the [*translation-unit*](basic.link#nt:translation-unit "6.7Program and linkage[basic.link]") is also considered a point of instantiation,
and
- [(7.2)](#temp.point-7.2)
for any such specialization that has a point of instantiation
within the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]"),
the end of the translation unit is also
considered a point of instantiation[.](#temp.point-7.sentence-1)
A specialization for a class template has at most one point of instantiation
within a translation unit[.](#temp.point-7.sentence-2)
A specialization for any template may have points of instantiation in multiple
translation units[.](#temp.point-7.sentence-3)
If two different points of instantiation give a template specialization
different meanings according to the [one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]"),
the program is ill-formed, no diagnostic required[.](#temp.point-7.sentence-4)
[8](#temp.point-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6161)
For the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements")),
the point of instantiation is the point of instantiation
of its enclosing templated entity, if any[.](#temp.point-8.sentence-1)
Otherwise, it immediately follows the namespace-scope declaration
or definition that contains the expansion statement[.](#temp.point-8.sentence-2)
#### [13.8.4.2](#temp.dep.candidate) Candidate functions [[temp.dep.candidate]](temp.dep.candidate)
[1](#temp.dep.candidate-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6171)
If a dependent call ([[temp.dep]](temp.dep "13.8.3Dependent names")) would be ill-formed or
would find a better match had the lookup for its dependent name
considered all the function declarations with external linkage
introduced in the associated namespaces in all translation units,
not just considering those declarations found in the template definition and
template instantiation contexts ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup")),
then the program is ill-formed, no diagnostic required[.](#temp.dep.candidate-1.sentence-1)
[2](#temp.dep.candidate-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6181)
[*Example [1](#temp.dep.candidate-example-1)*:
Source file "X.h":namespace Q {struct X { };}
Source file "G.h":namespace Q {void g_impl(X, X);}
Module interface unit of M1:module;#include "X.h"#include "G.h"export module M1;export template<typename T>void g(T t) { g_impl(t, Q::X{ }); // ADL in definition context finds Q::g_impl, g_impl not discarded}
Module interface unit of M2:module;#include "X.h"export module M2;import M1;void h(Q::X x) { g(x); // OK} — *end example*]
[3](#temp.dep.candidate-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6217)
[*Example [2](#temp.dep.candidate-example-2)*:
Module interface unit of Std:export module Std;export template<typename Iter>void indirect_swap(Iter lhs, Iter rhs){ swap(*lhs, *rhs); // swap not found by unqualified lookup, can be found only via ADL}
Module interface unit of M:export module M;import Std;
struct S { /* ...*/ };void swap(S&, S&); // #1void f(S* p, S* q){ indirect_swap(p, q); // finds #1 via ADL in instantiation context} — *end example*]
[4](#temp.dep.candidate-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6242)
[*Example [3](#temp.dep.candidate-example-3)*:
Source file "X.h":struct X { /* ... */ };
X operator+(X, X);
Module interface unit of F:export module F;export template<typename T>void f(T t) { t + t;}
Module interface unit of M:module;#include "X.h"export module M;import F;void g(X x) { f(x); // OK, instantiates f from F,// operator+ is visible in instantiation context} — *end example*]
[5](#temp.dep.candidate-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6269)
[*Example [4](#temp.dep.candidate-example-4)*:
Module interface unit of A:export module A;export template<typename T>void f(T t) { cat(t, t); // #1 dog(t, t); // #2}
Module interface unit of B:export module B;import A;export template<typename T, typename U>void g(T t, U u) { f(t);}
Source file "foo.h", not an importable header:struct foo {friend int cat(foo, foo);};int dog(foo, foo);
Module interface unit of C1:module;#include "foo.h" // dog not referenced, discardedexport module C1;import B;export template<typename T>void h(T t) { g(foo{ }, t);}
Translation unit:import C1;void i() { h(0); // error: dog not found at #2}
Importable header "bar.h":struct bar {friend int cat(bar, bar);};int dog(bar, bar);
Module interface unit of C2:module;#include "bar.h" // imports header unit "bar.h"export module C2;import B;export template<typename T>void j(T t) { g(bar{ }, t);}
Translation unit:import C2;void k() { j(0); // OK, dog found in instantiation context:// visible at end of module interface unit of C2} — *end example*]

View File

@@ -0,0 +1,39 @@
[temp.dep.splice]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.splice)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#splice)
#### 13.8.3.5 Dependent splice specifiers [temp.dep.splice]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5967)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") is dependent
if its converted [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") is value-dependent[.](#1.sentence-1)
A [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") is dependent or
if any of its template arguments are dependent[.](#1.sentence-2)
A [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") is dependent
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5977)
[*Example [1](#example-1)*: template<auto T, auto NS>void fn() {using a = [:T:]<1>; // [:T:]<1> is dependent because [:T:] is dependentstatic_assert([:NS:]::template TCls<1>::v == a::v); // [:NS:] is dependent}namespace N {template <auto V> struct TCls { static constexpr int v = V; };}int main() { fn<^^N::TCls, ^^N>();} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5996)
[*Example [2](#example-2)*: template<template<class> class X>struct S {[:^^X:]<int, float> m;};
template<class> struct V1 {};template<class, class = int> struct V2 {};
S<V1> s1; // error: V1<int, float> has too many template arguments S<V2> s2; // OK — *end example*]

44
cppdraft/temp/dep/temp.md Normal file
View File

@@ -0,0 +1,44 @@
[temp.dep.temp]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.temp)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#temp)
#### 13.8.3.7 Dependent template arguments [temp.dep.temp]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6042)
A type[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if the type it specifies is dependent[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6047)
A constant[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if its type is dependent or the constant
expression it specifies is value-dependent[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6053)
Furthermore, a constant[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is dependent if the corresponding constant template parameter
is of reference or pointer type and the [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") designates or points to a member of the current instantiation or a member of
a dependent type[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6061)
A template argument is also dependent if it is a pack expansion[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6065)
A template template parameter is dependent if
it names a template parameter or
its terminal name is dependent[.](#5.sentence-1)

306
cppdraft/temp/dep/type.md Normal file
View File

@@ -0,0 +1,306 @@
[temp.dep.type]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.dep.type)
### 13.8.3 Dependent names [[temp.dep]](temp.dep#type)
#### 13.8.3.2 Dependent types [temp.dep.type]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5358)
A name or [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") refers to the[*current instantiation*](#def:current_instantiation "13.8.3.2Dependent types[temp.dep.type]") if it is
- [(1.1)](#1.1)
in the definition of a class template, a nested class of a class template,
a member of a class template, or a member of a nested class of a class template,
the [injected-class-name](class.pre#def:injected-class-name "11.1Preamble[class.pre]") of the class template or nested class,
- [(1.2)](#1.2)
in the definition of a primary class template
or a member of a primary class template, the name of the
class template followed by the template argument list of
its [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") ([[temp.arg]](temp.arg "13.4Template arguments")) enclosed in<> (or an equivalent template alias specialization),
- [(1.3)](#1.3)
in the definition of a nested class of a class template,
the name of the nested class referenced as a member of the
current instantiation,
- [(1.4)](#1.4)
in the definition of a class template partial specialization
or a member of a class template partial specialization, the name of
the class template followed by a template argument list
equivalent to that of the partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"))
enclosed in <> (or an equivalent template alias specialization), or
- [(1.5)](#1.5)
in the definition of a templated function,
the name of a local class ([[class.local]](class.local "11.6Local class declarations"))[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5388)
A template argument that is equivalent to a template
parameter can be used in place of that
template parameter in a reference to the current instantiation[.](#2.sentence-1)
A template argument is equivalent to a type template parameter
if it denotes the same type[.](#2.sentence-2)
A template argument is equivalent to a constant template parameter
if it is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that names a variable
that is equivalent to the template parameter[.](#2.sentence-3)
A variable is equivalent to a template parameter if
- [(2.1)](#2.1)
it has the same type as the template parameter
(ignoring cv-qualification) and
- [(2.2)](#2.2)
its initializer consists of a single [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that names the template parameter or, recursively, such a variable[.](#2.sentence-4)
[*Note [1](#note-1)*:
Using a parenthesized variable name breaks the equivalence[.](#2.sentence-5)
— *end note*]
[*Example [1](#example-1)*: template <class T> class A { A* p1; // A is the current instantiation A<T>* p2; // A<T> is the current instantiation A<T*> p3; // A<T*> is not the current instantiation::A<T>* p4; // ::A<T> is the current instantiationclass B { B* p1; // B is the current instantiation A<T>::B* p2; // A<T>::B is the current instantiationtypename A<T*>::B* p3; // A<T*>::B is not the current instantiation};};
template <class T> class A<T*> { A<T*>* p1; // A<T*> is the current instantiation A<T>* p2; // A<T> is not the current instantiation};
template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; // refers to the current instantiation B<T2, T1, I>* b2; // not the current instantiationtypedef T1 my_T1; static const int my_I = I; static const int my_I2 = I+0; static const int my_I3 = my_I; static const long my_I4 = I; static const int my_I5 = (I);
B<my_T1, T2, my_I>* b3; // refers to the current instantiation B<my_T1, T2, my_I2>* b4; // not the current instantiation B<my_T1, T2, my_I3>* b5; // refers to the current instantiation B<my_T1, T2, my_I4>* b6; // not the current instantiation B<my_T1, T2, my_I5>* b7; // not the current instantiation}; — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5446)
A [*dependent base class*](#def:base_class,dependent "13.8.3.2Dependent types[temp.dep.type]") is a base class that is a dependent type and is
not the current instantiation[.](#3.sentence-1)
[*Note [2](#note-2)*:
A base class can be the current instantiation in the case of a nested class
naming an enclosing class as a base[.](#3.sentence-2)
[*Example [2](#example-2)*: template<class T> struct A {typedef int M; struct B {typedef void M; struct C; };};
template<class T> struct A<T>::B::C : A<T> { M m; // OK, A<T>::M}; — *end example*]
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5470)
A qualified ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup")) or unqualified name is a[*member of the current instantiation*](#def:current_instantiation,member_of_the "13.8.3.2Dependent types[temp.dep.type]") if
- [(4.1)](#4.1)
its lookup context, if it is a qualified name,
is the current instantiation, and
- [(4.2)](#4.2)
lookup for it finds any member of a class that is the current instantiation
[*Example [3](#example-3)*: template <class T> class A {static const int i = 5; int n1[i]; // i refers to a member of the current instantiationint n2[A::i]; // A::i refers to a member of the current instantiationint n3[A<T>::i]; // A<T>::i refers to a member of the current instantiationint f();};
template <class T> int A<T>::f() {return i; // i refers to a member of the current instantiation} — *end example*]
A qualified or unqualified name names a [*dependent member of the current instantiation*](#def:current_instantiation,dependent_member_of_the "13.8.3.2Dependent types[temp.dep.type]") if it is a
member of the current instantiation that, when looked up, refers to at least
one member declaration
(including a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") whose terminal name is dependent)
of a class that is the current instantiation[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5505)
A qualified name ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup")) is dependent if
- [(5.1)](#5.1)
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") is dependent, or
- [(5.2)](#5.2)
its lookup context is dependent and is not the current instantiation, or
- [(5.3)](#5.3)
its lookup context is the current instantiation and
it is operator=,[117](#footnote-117 "Every instantiation of a class template declares a different set of assignment operators.") or
- [(5.4)](#5.4)
its lookup context is the current instantiation and
has at least one dependent base class, and
qualified name lookup for the name finds nothing ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup"))[.](#5.sentence-1)
[*Example [4](#example-4)*: struct A {using B = int;
A f();};struct C : A {};template<class T>void g(T t) {decltype(t.A::f())::B i; // error: typename needed to interpret B as a type}template void g(C); // …even though A is ::A here — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5541)
If, for a given set of template arguments, a specialization of a template is
instantiated that refers to a member of the current instantiation with a
qualified name, the name is looked up in the
template instantiation context[.](#6.sentence-1)
If the result of this lookup differs from the
result of name lookup in the template definition context, name lookup is
ambiguous[.](#6.sentence-2)
[*Example [5](#example-5)*: struct A {int m;};
struct B {int m;};
template<typename T>struct C : A, T {int f() { return this->m; } // finds A::m in the template definition contextint g() { return m; } // finds A::m in the template definition context};
template int C<B>::f(); // error: finds both A::m and B::mtemplate int C<B>::g(); // OK, transformation to class member access syntax// does not occur in the template definition context; see [[expr.prim.id.general]](expr.prim.id.general "7.5.5.1General") — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5570)
An initializer is dependent if
any constituent expression ([[intro.execution]](intro.execution "6.10.1Sequential execution")) of the initializer
is type-dependent[.](#7.sentence-1)
A placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1General")) is dependent if
it designates a type deduced from a dependent initializer[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5577)
A placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))
is dependent if
- [(8.1)](#8.1)
it has a dependent initializer, or
- [(8.2)](#8.2)
it refers to an alias template
that is a member of the current instantiation and
whose [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") is dependent after
class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction"))
and substitution ([[temp.alias]](temp.alias "13.7.8Alias templates"))[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5591)
[*Example [6](#example-6)*: template<class T, class V>struct S { S(T); };
template<class U>struct A {template<class T> using X = S<T, U>; template<class T> using Y = S<T, int>; void f() {new X(1); // dependentnew Y(1); // not dependent}}; — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5609)
A type is dependent if it is
- [(10.1)](#10.1)
a template parameter,
- [(10.2)](#10.2)
denoted by a dependent (qualified) name,
- [(10.3)](#10.3)
a nested class or enumeration that is a direct member of
a class that is the current instantiation,
- [(10.4)](#10.4)
a cv-qualified type where the cv-unqualified type is dependent,
- [(10.5)](#10.5)
a compound type constructed from any dependent type,
- [(10.6)](#10.6)
an array type whose element type is dependent or whose
bound (if any) is value-dependent,
- [(10.7)](#10.7)
a function type whose parameters include one or more function parameter packs,
- [(10.8)](#10.8)
a function type whose exception specification is value-dependent,
- [(10.9)](#10.9)
denoted by a dependent placeholder type,
- [(10.10)](#10.10)
denoted by a dependent placeholder for a deduced class type,
- [(10.11)](#10.11)
denoted by a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") in which either the template name is a template parameter or any of the
template arguments is dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7Dependent template arguments")),[118](#footnote-118 "This includes an injected-class-name ([class.pre]) of a class template used without a template-argument-list.")
- [(10.12)](#10.12)
a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]"),
- [(10.13)](#10.13)
denoted by decltype([*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")),
where [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is [type-dependent](temp.dep.expr "13.8.3.3Type-dependent expressions[temp.dep.expr]"), or
- [(10.14)](#10.14)
denoted by a [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") in which either
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5Dependent splice specifiers"))[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5651)
[*Note [3](#note-3)*:
Because typedefs do not introduce new types, but
instead simply refer to other types, a name that refers to a
typedef that is a member of the current instantiation is dependent
only if the type referred to is dependent[.](#11.sentence-1)
— *end note*]
[117)](#footnote-117)[117)](#footnoteref-117)
Every instantiation of a class template declares
a different set of assignment operators[.](#footnote-117.sentence-1)
[118)](#footnote-118)[118)](#footnoteref-118)
This includes an injected-class-name ([[class.pre]](class.pre "11.1Preamble")) of a class template
used without a [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")[.](#footnote-118.sentence-1)

380
cppdraft/temp/expl/spec.md Normal file
View File

@@ -0,0 +1,380 @@
[temp.expl.spec]
# 13 Templates [[temp]](./#temp)
## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#temp.expl.spec)
### 13.9.4 Explicit specialization [temp.expl.spec]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7093)
An explicit specialization of any of the following:
- [(1.1)](#1.1)
function template
- [(1.2)](#1.2)
class template
- [(1.3)](#1.3)
variable template
- [(1.4)](#1.4)
member function of a class template
- [(1.5)](#1.5)
static data member of a class template
- [(1.6)](#1.6)
member class of a class template
- [(1.7)](#1.7)
member enumeration of a class template
- [(1.8)](#1.8)
member class template of a class or class template
- [(1.9)](#1.9)
member function template of a class or class template
can be declared by a declaration introduced bytemplate<>;
that is:
[explicit-specialization:](#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]")
template < > [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")
[*Example [1](#example-1)*: template<class T> class stream;
template<> class stream<char> { /* ... */ }; // #1template<class T> class Array { /* ... */ };template<class T> void sort(Array<T>& v) { /* ... */ }template<> void sort<int>(Array<int>&); // #2template<> void sort(Array<char*>&); // #3 template argument is deduced ([[temp.arg.explicit]](temp.arg.explicit "13.10.2Explicit template argument specification"))
Given these declarations,
#1 will be used as the definition of streams ofchars;
other streams will be handled by class template specializations instantiated
from the class template[.](#1.sentence-2)
Similarly,
#2 will be used as the sort function for arguments of
type Array<int> and
#3 will be used for arguments
of typeArray<char*>;
otherArray types will be sorted by functions generated from the function template[.](#1.sentence-3)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7155)
The [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in an [*explicit-specialization*](#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]") shall not be an [*export-declaration*](module.interface#nt:export-declaration "10.2Export declaration[module.interface]")[.](#2.sentence-1)
An explicit specialization shall not use
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))
other than thread_local[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7162)
An explicit specialization
may be declared in any scope in which the corresponding primary template
may be defined ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[class.mem]](class.mem "11.4Class members"), [[temp.mem]](temp.mem "13.7.3Member templates"))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7167)
An explicit specialization does not introduce a name ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#4.sentence-1)
A declaration of a function template, class template, or variable template being explicitly
specialized shall be reachable from the declaration of
the explicit specialization[.](#4.sentence-2)
[*Note [1](#note-1)*:
A declaration, but not a definition of the template is needed[.](#4.sentence-3)
— *end note*]
The definition of a class or class template shall be reachable from the
declaration of an explicit specialization for a member template of the class
or class template[.](#4.sentence-4)
[*Example [2](#example-2)*: template<> class X<int> { /* ... */ }; // error: X not a templatetemplate<class T> class X;
template<> class X<char*> { /* ... */ }; // OK, X is a template — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7188)
A member function, a member function template, a member class,
a member enumeration, a
member class template,
a static data member, or a static data member template of a class template
may be explicitly specialized for a class specialization that is implicitly
instantiated;
in this case, the definition of the class template shall
be reachable from the explicit specialization for the member of the class
template[.](#5.sentence-1)
If such an explicit specialization for the member of a class template names an
implicitly-declared special member function ([[special]](special "11.4.4Special member functions")),
the program is ill-formed[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7202)
A member of an explicitly specialized class is not implicitly
instantiated from the member declaration of the class template;
instead, the member of the class template specialization shall itself be
explicitly defined if its definition is required[.](#6.sentence-1)
The definition of the class template explicit specialization
shall be reachable from the definition of any member of it[.](#6.sentence-2)
The definition of an explicitly specialized class is unrelated to the
definition of a generated specialization[.](#6.sentence-3)
That is, its members need
not have the same names, types, etc. as the members of a generated
specialization[.](#6.sentence-4)
Members of an explicitly specialized
class template are defined in the same manner as members of normal classes, and
not using the template<> syntax[.](#6.sentence-5)
The same is true when defining a member of an explicitly specialized member
class[.](#6.sentence-6)
However, template<> is used in defining a member of an explicitly
specialized member class template that is specialized as a class template[.](#6.sentence-7)
[*Example [3](#example-3)*: template<class T> struct A {struct B { }; template<class U> struct C { };};
template<> struct A<int> {void f(int);};
void h() { A<int> a;
a.f(16); // A<int>::f must be defined somewhere}// template<> not used for a member of an explicitly specialized class templatevoid A<int>::f(int) { /* ... */ }template<> struct A<char>::B {void f();};// template<> also not used when defining a member of an explicitly specialized member classvoid A<char>::B::f() { /* ... */ }template<> template<class U> struct A<char>::C {void f();};// template<> is used when defining a member of an explicitly specialized member class template// specialized as a class templatetemplate<>template<class U> void A<char>::C<U>::f() { /* ... */ }template<> struct A<short>::B {void f();};template<> void A<short>::B::f() { /* ... */ } // error: template<> not permittedtemplate<> template<class U> struct A<short>::C {void f();};template<class U> void A<short>::C<U>::f() { /* ... */ } // error: template<> required — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7265)
If a template, a member template or a member of a class template is explicitly
specialized, a declaration of that specialization shall be reachable from
every use of
that specialization that would cause an implicit instantiation to take place,
in every translation unit in which such a use occurs;
no diagnostic is required[.](#7.sentence-1)
If the program does not provide a definition for an explicit specialization and
either the specialization is used in a way that would cause an implicit
instantiation to take place or the member is a virtual member function,
the program is ill-formed, no diagnostic required[.](#7.sentence-2)
An implicit instantiation is never generated for an explicit specialization
that is declared but not defined[.](#7.sentence-3)
[*Example [4](#example-4)*: class String { };template<class T> class Array { /* ... */ };template<class T> void sort(Array<T>& v) { /* ... */ }void f(Array<String>& v) { sort(v); // use primary template sort(Array<T>&), T is String}template<> void sort<String>(Array<String>& v); // error: specialization after use of primary templatetemplate<> void sort<>(Array<char*>& v); // OK, sort<char*> not yet usedtemplate<class T> struct A {enum E : T; enum class S : T;};template<> enum A<int>::E : int { eint }; // OKtemplate<> enum class A<int>::S : int { sint }; // OKtemplate<class T> enum A<T>::E : T { eT };template<class T> enum class A<T>::S : T { sT };template<> enum A<char>::E : char { echar }; // error: A<char>::E was instantiated// when A<char> was instantiatedtemplate<> enum class A<char>::S : char { schar }; // OK — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7304)
The placement of explicit specialization declarations for function templates, class
templates, variable templates,
member functions of class templates, static data members of class
templates, member classes of class templates, member enumerations of class
templates, member class templates of class
templates, member function templates of class templates,
static data member templates of class templates,
member functions of
member templates of class templates, member functions of member templates of
non-template classes,
static data member templates of non-template classes,
member function templates of member classes of class
templates, etc., and the placement of partial specialization declarations
of class templates, variable templates,
member class templates of non-template classes,
static data member templates of non-template classes, member
class templates of class templates, etc., can affect whether a program is
well-formed according to the relative positioning of the explicit specialization
declarations and their points of instantiation in the translation unit as
specified above and below[.](#8.sentence-1)
When writing a specialization, be careful about its location;
or to make it compile will be such a trial as to kindle its self-immolation[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7328)
[*Note [2](#note-2)*:
A class template explicit specialization that has been declared but
not defined can be used exactly like other
incompletely-defined classes ([[basic.types]](basic.types "6.9Types"))[.](#9.sentence-1)
[*Example [5](#example-5)*: template<class T> class X; // X is a class templatetemplate<> class X<int>;
X<int>* p; // OK, pointer to declared class X<int> X<int> x; // error: object of incomplete class X<int> — *end example*]
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7344)
[*Note [3](#note-3)*:
An explicit specialization of a constrained template needs
to satisfy that template's associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))[.](#10.sentence-1)
The satisfaction of constraints is determined
when forming the template name of an explicit specialization
in which all template arguments are specified ([[temp.names]](temp.names "13.3Names of template specializations")),
or, for explicit specializations of function templates,
during template argument deduction ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7Deducing template arguments from a function declaration"))
when one or more trailing template arguments are left unspecified[.](#10.sentence-2)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7356)
A function with the same name as a template and a type that exactly matches that
of a template specialization is not an explicit specialization ([[temp.fct]](temp.fct "13.7.7Function templates"))[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7360)
Whether an explicit specialization of a function or variable template
is inline, constexpr, constinit, or consteval
is determined by the explicit specialization and
is independent of those properties of the template[.](#12.sentence-1)
Similarly,
attributes and [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* appearing in the declaration of a template
have no effect on an explicit specialization of that template[.](#12.sentence-2)
[*Example [6](#example-6)*: template<class T> void f(T) { /* ... */ }template<class T> inline T g(T) { /* ... */ }template<> inline void f<>(int) { /* ... */ } // OK, inlinetemplate<> int g<>(int) { /* ... */ } // OK, not inlinetemplate<typename> [[noreturn]] void h([[maybe_unused]] int i);template<> void h<int>(int i) {// Implementations are expected not to warn that the function returns// but can warn about the unused parameter.} — *end example*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7385)
An explicit specialization of a static data member of a template
or an explicit specialization of a static data member template is a
definition if the declaration includes an initializer;
otherwise, it is a declaration[.](#13.sentence-1)
[*Note [4](#note-4)*:
The definition of a static data member of a template
for which default-initialization is desired
can use functional cast notation ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")):template<> X Q<int>::x; // declarationtemplate<> X Q<int>::x (); // error: declares a functiontemplate<> X Q<int>::x = X(); // definition
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7401)
A member or a member template of a class template may be explicitly specialized
for a given implicit instantiation of the class template, even if the member
or member template is defined in the class template definition[.](#14.sentence-1)
An explicit specialization of a member or member template is specified using the
syntax for explicit specialization[.](#14.sentence-2)
[*Example [7](#example-7)*: template<class T> struct A {void f(T); template<class X1> void g1(T, X1); template<class X2> void g2(T, X2); void h(T) { }};
// specializationtemplate<> void A<int>::f(int);
// out of class member template definitiontemplate<class T> template<class X1> void A<T>::g1(T, X1) { }// member template specializationtemplate<> template<class X1> void A<int>::g1(int, X1);
// member template specializationtemplate<> template<>void A<int>::g1(int, char); // X1 deduced as chartemplate<> template<>void A<int>::g2<char>(int, char); // X2 specified as char// member specialization even if defined in class definitiontemplate<> void A<int>::h(int) { } — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7436)
A member or a member template may be nested within many enclosing class
templates[.](#15.sentence-1)
In an explicit specialization for such a member,
the member declaration shall be preceded by atemplate<> for each enclosing class template that is explicitly specialized[.](#15.sentence-2)
[*Example [8](#example-8)*: template<class T1> class A {template<class T2> class B {void mf(); };};template<> template<> class A<int>::B<double>;template<> template<> void A<char>::B<char>::mf(); — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7455)
In an explicit specialization declaration for a member of a class template or
a member template that appears in namespace scope,
the member template and some of its enclosing class templates may remain
unspecialized,
except that the declaration shall not explicitly specialize a class member
template if its enclosing class templates are not explicitly specialized
as well[.](#16.sentence-1)
In such an explicit specialization declaration, the keywordtemplate followed by a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") shall be provided instead of thetemplate<> preceding the explicit specialization declaration of the member[.](#16.sentence-2)
The types of the[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* in the[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") shall be the same as those specified in the primary template definition[.](#16.sentence-3)
[*Example [9](#example-9)*: template <class T1> class A {template<class T2> class B {template<class T3> void mf1(T3); void mf2(); };};template <> template <class X>class A<int>::B {template <class T> void mf1(T); };template <> template <> template<class T>void A<int>::B<double>::mf1(T t) { }template <class Y> template <>void A<Y>::B<double>::mf2() { } // error: B<double> is specialized but// its enclosing class template A is not — *end example*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7495)
A specialization of a member function template, member class template,
or static data member template of
a non-specialized class template is itself a template[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7500)
An explicit specialization declaration shall not be a friend declaration[.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7503)
Default function arguments shall not be specified in a declaration or
a definition for one of the following explicit specializations:
- [(19.1)](#19.1)
the explicit specialization of a function template;
- [(19.2)](#19.2)
the explicit specialization of a member function template;
- [(19.3)](#19.3)
the explicit specialization of a member function of a class template where
the class template specialization to which the member function specialization
belongs is implicitly instantiated[.](#19.sentence-1)
[*Note [5](#note-5)*:
Default function arguments can be specified in the declaration or
definition of a member function of a class template specialization that is
explicitly specialized[.](#19.3.sentence-2)
— *end note*]

214
cppdraft/temp/explicit.md Normal file
View File

@@ -0,0 +1,214 @@
[temp.explicit]
# 13 Templates [[temp]](./#temp)
## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#temp.explicit)
### 13.9.3 Explicit instantiation [temp.explicit]
[1](#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[.](#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[.](#1.sentence-2)
[2](#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.3Explicit instantiation[temp.explicit]")
externopt template [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")
There are two forms of explicit instantiation: an explicit instantiation
definition and an explicit instantiation declaration[.](#2.sentence-2)
An explicit instantiation
declaration begins with the extern keyword[.](#2.sentence-3)
[3](#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.2Storage class specifiers[dcl.stc]") ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))
other than thread_local[.](#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[.](#3.sentence-2)
No [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1Attribute syntax and semantics"))
shall appertain to an explicit instantiation[.](#3.sentence-3)
[4](#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.5Elaborated type specifiers[dcl.type.elab]") in the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") shall include a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]");
otherwise, the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") shall be a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]") whose [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") comprises a single [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") that does not have an [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#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.2Unqualified names[expr.prim.id.unqual]") in the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall be a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#4.sentence-2)
[*Example [1](#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.2Explicit template argument specification"))namespace N {template<class T> void f(T&) { }}template void N::f<int>(int&); — *end example*]
[5](#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.1General"))[.](#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[.](#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[.](#5.sentence-3)
If the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") of the explicit instantiation names an implicitly-declared special member
function ([[special]](special "11.4.4Special member functions")), the program is ill-formed[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6985)
The [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3Explicit instantiation[temp.explicit]") and
the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") produced by the corresponding substitution
into the templated function, variable, or class
are two declarations of the same entity[.](#6.sentence-1)
[*Note [1](#note-1)*:
These declarations need to have matching types as specified in [[basic.link]](basic.link "6.7Program and linkage"), except as specified in [[except.spec]](except.spec "14.5Exception specifications")[.](#6.sentence-2)
[*Example [2](#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.7Placeholder type specifiers")) — *end example*]
— *end note*]
Despite its syntactic form, the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3Explicit 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[.](#6.sentence-3)
[7](#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[.](#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[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7021)
[*Note [2](#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.3Constrained declarations"))[.](#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.3Names of template specializations")),
or, for explicit instantiations of function templates,
during template argument deduction ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7Deducing template arguments from a function declaration"))
when one or more trailing template arguments are left unspecified[.](#8.sentence-2)
— *end note*]
[9](#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.3Constrained declarations"), [[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")),
except as described below[.](#9.sentence-1)
[*Note [3](#note-3)*:
In addition, it will typically be an explicit instantiation of certainimplementation-dependent data about the class[.](#9.sentence-2)
— *end note*]
[10](#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[.](#10.sentence-1)
[11](#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.7Destructors"))
shall correspond to the selected destructor of the class[.](#11.sentence-1)
[12](#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[.](#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.2Implicit 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[.](#12.sentence-2)
[*Note [4](#note-4)*:
This rule does apply to inline functions even though an
explicit instantiation declaration of such an entity has no other normative
effect[.](#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[.](#12.sentence-4)
— *end note*]
An explicit instantiation declaration shall not name a specialization of a
template with internal linkage[.](#12.sentence-5)
[13](#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[.](#13.sentence-1)
[*Example [3](#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*]

520
cppdraft/temp/fct.md Normal file
View File

@@ -0,0 +1,520 @@
[temp.fct]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.fct)
### 13.7.7 Function templates [temp.fct]
#### [13.7.7.1](#general) General [[temp.fct.general]](temp.fct.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4052)
A function template defines an unbounded set of related functions[.](#general-1.sentence-1)
[*Example [1](#general-example-1)*:
A family of sort functions can be declared like this:template<class T> class Array { };template<class T> void sort(Array<T>&);
— *end example*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4062)
[*Note [1](#general-note-1)*:
A function template can have the same name as other function templates
and non-template functions ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) in the same scope[.](#general-2.sentence-1)
— *end note*]
A non-template function is not
related to a function template
(i.e., it is never considered to be a specialization),
even if it has the same name and type
as a potentially generated function template specialization[.](#general-2.sentence-2)[115](#footnote-115 "That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name. If such a non-template function is odr-used ([term.odr.use]) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.")
[115)](#footnote-115)[115)](#footnoteref-115)
That is,
declarations of non-template functions do not merely guide
overload resolution of
function template specializations
with the same name[.](#footnote-115.sentence-1)
If such a non-template function is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a program, it must be defined;
it will not be implicitly instantiated using the function template definition[.](#footnote-115.sentence-2)
#### [13.7.7.2](#temp.over.link) Function template overloading [[temp.over.link]](temp.over.link)
[1](#temp.over.link-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4084)
It is possible to overload function templates so that two different
function template specializations have the same type[.](#temp.over.link-1.sentence-1)
[*Example [1](#temp.over.link-example-1)*:
// translation unit 1:template<class T>void f(T*);void g(int* p) { f(p); // calls f<int>(int*)}
// translation unit 2:template<class T>void f(T);void h(int* p) { f(p); // calls f<int*>(int*)}
— *end example*]
[2](#temp.over.link-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4112)
Such specializations are distinct functions and do not violate the[one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]")[.](#temp.over.link-2.sentence-1)
[3](#temp.over.link-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4116)
The signature of a function template
is defined in [[intro.defs]](intro.defs "3Terms and definitions")[.](#temp.over.link-3.sentence-1)
The names of the template parameters are significant only for establishing
the relationship between the template parameters and the rest of the
signature[.](#temp.over.link-3.sentence-2)
[*Note [1](#temp.over.link-note-1)*:
Two distinct function templates can have identical function return types and
function parameter lists, even if overload resolution alone cannot distinguish
them[.](#temp.over.link-3.sentence-3)
template<class T> void f();template<int I> void f(); // OK, overloads the first template// distinguishable with an explicit template argument list — *end note*]
[4](#temp.over.link-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4134)
When an expression that references a template parameter is used in the
function parameter list or the return type in the declaration of a
function template, the expression that references the template
parameter is part of the signature of the function template[.](#temp.over.link-4.sentence-1)
This is
necessary to permit a declaration of a function template in one
translation unit to be linked with another declaration of the function
template in another translation unit and, conversely, to ensure that
function templates that are intended to be distinct are not linked
with one another[.](#temp.over.link-4.sentence-2)
[*Example [2](#temp.over.link-example-2)*: template <int I, int J> A<I+J> f(A<I>, A<J>); // #1template <int K, int L> A<K+L> f(A<K>, A<L>); // same as #1template <int I, int J> A<I-J> f(A<I>, A<J>); // different from #1 — *end example*]
[*Note [2](#temp.over.link-note-2)*:
Most expressions that use template parameters use constant template
parameters, but it is possible for an expression to reference a type
parameter[.](#temp.over.link-4.sentence-3)
For example, a template type parameter can be used in thesizeof operator[.](#temp.over.link-4.sentence-4)
— *end note*]
[5](#temp.over.link-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4160)
Two expressions involving template parameters are considered[*equivalent*](#def:equivalent,expressions "13.7.7.2Function template overloading[temp.over.link]") if two function definitions containing the expressions would satisfy
the [one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]"), except that the tokens used
to name the template parameters may differ as long as a token used to
name a template parameter in one expression is replaced by another token
that names the same template parameter in the other expression[.](#temp.over.link-5.sentence-1)
Two unevaluated operands that do not involve template parameters
are considered equivalent
if two function definitions containing the expressions
would satisfy the one-definition rule,
except that the tokens used to name types and declarations may differ
as long as they name the same entities, and
the tokens used to form concept-ids ([[temp.names]](temp.names "13.3Names of template specializations")) may differ
as long as the two [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")*s* are the same ([[temp.type]](temp.type "13.6Type equivalence"))[.](#temp.over.link-5.sentence-2)
[*Note [3](#temp.over.link-note-3)*:
For instance, A<42> and A<40+2> name the same type[.](#temp.over.link-5.sentence-3)
— *end note*]
Two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* are never considered equivalent[.](#temp.over.link-5.sentence-4)
[*Note [4](#temp.over.link-note-4)*:
The intent is to avoid [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* appearing in the
signature of a function template with external linkage[.](#temp.over.link-5.sentence-5)
— *end note*]
For determining whether two dependent names ([[temp.dep]](temp.dep "13.8.3Dependent names")) are equivalent,
only the name itself is considered, not the result of name lookup[.](#temp.over.link-5.sentence-6)
[*Note [5](#temp.over.link-note-5)*:
If such a dependent name is unqualified,
it is looked up from
a first declaration of the function template ([[temp.res.general]](temp.res.general "13.8.1General"))[.](#temp.over.link-5.sentence-7)
— *end note*]
[*Example [3](#temp.over.link-example-3)*: template <int I, int J> void f(A<I+J>); // #1template <int K, int L> void f(A<K+L>); // same as #1template <class T> decltype(g(T())) h();int g(int);template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup…{ return g(T()); } // … although the lookup here does find g(int)int i = h<int>(); // template argument substitution fails; g(int)// not considered at the first declaration of h()// ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalenttemplate <int N> void foo(const char (*s)[([]{}, N)]);template <int N> void foo(const char (*s)[([]{}, N)]);
// two different declarations because the non-dependent portions are not considered equivalenttemplate <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]); — *end example*]
Two potentially-evaluated expressions involving template parameters that are not equivalent are[*functionally equivalent*](#def:functionally_equivalent,expressions "13.7.7.2Function template overloading[temp.over.link]") if, for any given set of template arguments, the evaluation of the
expression results in the same value[.](#temp.over.link-5.sentence-8)
Two unevaluated operands that are not equivalent
are functionally equivalent if, for any given set of template arguments,
the expressions perform
the same operations in the same order with the same entities[.](#temp.over.link-5.sentence-9)
[*Note [6](#temp.over.link-note-6)*:
For instance, one could have redundant parentheses[.](#temp.over.link-5.sentence-10)
— *end note*]
[*Example [4](#temp.over.link-example-4)*: template<int I> concept C = true;template<typename T> struct A {void f() requires C<42>; // #1void f() requires true; // OK, different functions}; — *end example*]
[6](#temp.over.link-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4235)
Two [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2Function template overloading[temp.over.link]") if
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* have the same length,
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are equivalent
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* that are equivalent
if either [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"),
and if either [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"),
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* are equivalent[.](#temp.over.link-6.sentence-1)
Two [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2Function template overloading[temp.over.link]") under the following conditions:
- [(6.1)](#temp.over.link-6.1)
they declare template parameters of the same kind,
- [(6.2)](#temp.over.link-6.2)
if either declares a template parameter pack, they both do,
- [(6.3)](#temp.over.link-6.3)
if they declare constant template parameters,
they have equivalent types
ignoring the use of [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* for placeholder types, and
- [(6.4)](#temp.over.link-6.4)
if they declare template template parameters,
their [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are equivalent[.](#temp.over.link-6.sentence-2)
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* are equivalent, the rules above are used to compare expressions
involving template parameters[.](#temp.over.link-6.sentence-3)
Two [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2Function template overloading[temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))
the same set of template argument lists[.](#temp.over.link-6.sentence-4)
[7](#temp.over.link-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4267)
If the validity or meaning of the program depends on
whether two constructs are equivalent, and they are
functionally equivalent but not equivalent, the program is ill-formed,
no diagnostic required[.](#temp.over.link-7.sentence-1)
Furthermore, if two declarations A and B of function templates
- [(7.1)](#temp.over.link-7.1)
introduce the same name,
- [(7.2)](#temp.over.link-7.2)
have corresponding signatures ([[basic.scope.scope]](basic.scope.scope "6.4.1General")),
- [(7.3)](#temp.over.link-7.3)
would declare the same entity,
when considering A and B to correspond in that determination ([[basic.link]](basic.link "6.7Program and linkage")), and
- [(7.4)](#temp.over.link-7.4)
accept and are satisfied by the same set of template argument lists,
but do not correspond,
the program is ill-formed, no diagnostic required[.](#temp.over.link-7.sentence-2)
[8](#temp.over.link-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4287)
[*Note [7](#temp.over.link-note-7)*:
This rule guarantees that equivalent declarations will be linked with
one another, while not requiring implementations to use heroic efforts
to guarantee that functionally equivalent declarations will be treated
as distinct[.](#temp.over.link-8.sentence-1)
For example, the last two declarations are functionally
equivalent and would cause a program to be ill-formed:// guaranteed to be the sametemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);
// guaranteed to be differenttemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+11>);
// ill-formed, no diagnostic requiredtemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+1+2+3+4>);
— *end note*]
#### [13.7.7.3](#temp.func.order) Partial ordering of function templates [[temp.func.order]](temp.func.order)
[1](#temp.func.order-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4312)
If multiple function templates share a name,
the use of that name can be ambiguous because
template argument deduction ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) may identify
a specialization for more than one function template[.](#temp.func.order-1.sentence-1)
[*Partial ordering*](#def:template,function,partial_ordering "13.7.7.3Partial ordering of function templates[temp.func.order]") of overloaded function template declarations is used in the following contexts
to select the function template to which a function template specialization
refers:
- [(1.1)](#temp.func.order-1.1)
during overload resolution for a call to a function template specialization ([[over.match.best]](over.match.best "12.2.4Best viable function"));
- [(1.2)](#temp.func.order-1.2)
when the address of a function template specialization is taken;
- [(1.3)](#temp.func.order-1.3)
when a placement operator delete that is a
function template
specialization
is selected to match a placement operator new ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"), [[expr.new]](expr.new "7.6.2.8New"));
- [(1.4)](#temp.func.order-1.4)
when a [friend function declaration](temp.friend "13.7.5Friends[temp.friend]"), an[explicit instantiation](temp.explicit "13.9.3Explicit instantiation[temp.explicit]") or an [explicit specialization](temp.expl.spec "13.9.4Explicit specialization[temp.expl.spec]") refers to
a function template specialization[.](#temp.func.order-1.sentence-2)
[2](#temp.func.order-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4339)
Partial ordering selects which of two function templates is more
specialized than the other by transforming each template in turn
(see next paragraph) and performing template argument deduction
using the function type[.](#temp.func.order-2.sentence-1)
The deduction process determines whether
one of the templates is more specialized than the other[.](#temp.func.order-2.sentence-2)
If so, the
more specialized template is the one chosen by the partial ordering
process[.](#temp.func.order-2.sentence-3)
If both deductions succeed, the partial ordering selects
the more constrained template (if one exists) as determined below[.](#temp.func.order-2.sentence-4)
[3](#temp.func.order-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4351)
To produce the transformed template, for each
type, constant,
type template, variable template, or concept
template parameter (including template parameter packs ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))
thereof) synthesize a unique type, value, class template,
variable template, or concept,
respectively, and substitute it for each occurrence of that parameter
in the function type of the template[.](#temp.func.order-3.sentence-1)
[*Note [1](#temp.func.order-note-1)*:
The type replacing the placeholder
in the type of the value synthesized for a constant template parameter
is also a unique synthesized type[.](#temp.func.order-3.sentence-2)
— *end note*]
[4](#temp.func.order-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4369)
A synthesized template has the same [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") as
its corresponding template template parameter[.](#temp.func.order-4.sentence-1)
[5](#temp.func.order-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4375)
Each function template M that is a member function
is considered to have
a new first parameter of type X(M), described below,
inserted in its function parameter list[.](#temp.func.order-5.sentence-1)
If exactly one of the function templates was considered by overload resolution
via a rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions"))
with a reversed order of parameters,
then the order of the function parameters in its transformed template
is reversed[.](#temp.func.order-5.sentence-2)
For a function template M with cv-qualifiers cv that is a member of a class A:
- [(5.1)](#temp.func.order-5.1)
The type X(M) is “rvalue reference to cv A”
if the optional [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") ofM is && or
if M has no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") and
the positionally-corresponding parameter of the other transformed template
has rvalue reference type;
if this determination depends recursively upon
whether X(M) is an rvalue reference type,
it is not considered to have rvalue reference type[.](#temp.func.order-5.1.sentence-1)
- [(5.2)](#temp.func.order-5.2)
Otherwise, X(M) is “lvalue reference to cv A”[.](#temp.func.order-5.2.sentence-1)
[*Note [2](#temp.func.order-note-2)*:
This allows a non-static
member to be ordered with respect to a non-member function and for the results
to be equivalent to the ordering of two equivalent non-members[.](#temp.func.order-5.sentence-4)
— *end note*]
[*Example [1](#temp.func.order-example-1)*: struct A { };template<class T> struct B {template<class R> int operator*(R&); // #1};
template<class T, class R> int operator*(T&, R&); // #2// The declaration of B::operator* is transformed into the equivalent of// template<class R> int operator*(B<A>&, R&); // #1aint main() { A a;
B<A> b;
b * a; // calls #1} — *end example*]
[6](#temp.func.order-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4428)
Using the transformed function template's function type,
perform type deduction against the other template as described in [[temp.deduct.partial]](temp.deduct.partial "13.10.3.5Deducing template arguments during partial ordering")[.](#temp.func.order-6.sentence-1)
[*Example [2](#temp.func.order-example-2)*: template<class T> struct A { A(); };
template<class T> void f(T);template<class T> void f(T*);template<class T> void f(const T*);
template<class T> void g(T);template<class T> void g(T&);
template<class T> void h(const T&);template<class T> void h(A<T>&);
void m() {const int* p;
f(p); // f(const T*) is more specialized than f(T) or f(T*)float x;
g(x); // ambiguous: g(T) or g(T&) A<int> z;
h(z); // overload resolution selects h(A<T>&)const A<int> z2;
h(z2); // h(const T&) is called because h(A<T>&) is not callable} — *end example*]
[7](#temp.func.order-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4459)
[*Note [3](#temp.func.order-note-3)*:
Since, in a call context, such type deduction considers only parameters
for which there are explicit call arguments, some parameters are ignored (namely,
function parameter packs, parameters with default arguments, and ellipsis
parameters)[.](#temp.func.order-7.sentence-1)
[*Example [3](#temp.func.order-example-3)*: template<class T> void f(T); // #1template<class T> void f(T*, int=1); // #2template<class T> void g(T); // #3template<class T> void g(T*, ...); // #4int main() {int* ip;
f(ip); // calls #2 g(ip); // calls #4} — *end example*]
[*Example [4](#temp.func.order-example-4)*: template<class T, class U> struct A { };
template<class T, class U> void f(U, A<U, T>* p = 0); // #1template< class U> void f(U, A<U, U>* p = 0); // #2template<class T > void g(T, T = T()); // #3template<class T, class... U> void g(T, U ...); // #4void h() { f<int>(42, (A<int, int>*)0); // calls #2 f<int>(42); // error: ambiguous g(42); // error: ambiguous} — *end example*]
[*Example [5](#temp.func.order-example-5)*: template<class T, class... U> void f(T, U...); // #1template<class T > void f(T); // #2template<class T, class... U> void g(T*, U...); // #3template<class T > void g(T); // #4void h(int i) { f(&i); // OK, calls #2 g(&i); // OK, calls #3} — *end example*]
— *end note*]
[8](#temp.func.order-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4512)
If deduction against the other template succeeds for both transformed templates,
constraints can be considered as follows:
- [(8.1)](#temp.func.order-8.1)
If their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* (possibly including [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* invented for an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))) or
function parameter lists differ in length,
neither template is more specialized than the other[.](#temp.func.order-8.1.sentence-1)
- [(8.2)](#temp.func.order-8.2)
Otherwise:
* [(8.2.1)](#temp.func.order-8.2.1)
If exactly one of the templates was considered by overload resolution
via a rewritten candidate with reversed order of parameters:
+
[(8.2.1.1)](#temp.func.order-8.2.1.1)
If, for either template, some of the template parameters
are not deducible from their function parameters,
neither template is more specialized than the other.
+
[(8.2.1.2)](#temp.func.order-8.2.1.2)
If there is either no reordering or more than one reordering
of the associated [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") such that
- [(8.2.1.2.1)](#temp.func.order-8.2.1.2.1)
the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* are equivalent and
- [(8.2.1.2.2)](#temp.func.order-8.2.1.2.2)
the function parameters that positionally correspond
between the two templates are of the same type,
neither template is more specialized than the other.
* [(8.2.2)](#temp.func.order-8.2.2)
Otherwise, if the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* are not equivalent ([[temp.over.link]](#temp.over.link "13.7.7.2Function template overloading")) or
if the function parameters that positionally correspond
between the two templates are not of the same type,
neither template is more specialized than the other[.](#temp.func.order-8.2.sentence-1)
- [(8.3)](#temp.func.order-8.3)
Otherwise, if the context in which the partial ordering is done
is that of a call to a conversion function and
the return types of the templates are not the same,
then neither template is more specialized than the other[.](#temp.func.order-8.3.sentence-1)
- [(8.4)](#temp.func.order-8.4)
Otherwise,
if one template is more constrained than the other ([[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints")),
the more constrained template is more specialized than the other[.](#temp.func.order-8.4.sentence-1)
- [(8.5)](#temp.func.order-8.5)
Otherwise, neither template is more specialized than the other[.](#temp.func.order-8.5.sentence-1)
[*Example [6](#temp.func.order-example-6)*: template <typename> constexpr bool True = true;template <typename T> concept C = True<T>;
void f(C auto &, auto &) = delete;template <C Q> void f(Q &, C auto &);
void g(struct A *ap, struct B *bp) { f(*ap, *bp); // OK, can use different methods to produce template parameters}template <typename T, typename U> struct X {};
template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete;template <C T, C U, C V> bool operator==(T, X<U, V>);
void h() { X<void *, int>{} == 0; // OK, correspondence of [T, U, V] and [U, V, T]} — *end example*]

View File

@@ -0,0 +1,49 @@
[temp.fct.general]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.fct.general)
### 13.7.7 Function templates [[temp.fct]](temp.fct#general)
#### 13.7.7.1 General [temp.fct.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4052)
A function template defines an unbounded set of related functions[.](#1.sentence-1)
[*Example [1](#example-1)*:
A family of sort functions can be declared like this:template<class T> class Array { };template<class T> void sort(Array<T>&);
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4062)
[*Note [1](#note-1)*:
A function template can have the same name as other function templates
and non-template functions ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) in the same scope[.](#2.sentence-1)
— *end note*]
A non-template function is not
related to a function template
(i.e., it is never considered to be a specialization),
even if it has the same name and type
as a potentially generated function template specialization[.](#2.sentence-2)[115](#footnote-115 "That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name. If such a non-template function is odr-used ([term.odr.use]) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.")
[115)](#footnote-115)[115)](#footnoteref-115)
That is,
declarations of non-template functions do not merely guide
overload resolution of
function template specializations
with the same name[.](#footnote-115.sentence-1)
If such a non-template function is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a program, it must be defined;
it will not be implicitly instantiated using the function template definition[.](#footnote-115.sentence-2)

1750
cppdraft/temp/fct/spec.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
[temp.fct.spec.general]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#general)
### 13.10.1 General [temp.fct.spec.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7526)
A function instantiated from a function template is called a function template
specialization; so is an explicit specialization of a function template[.](#1.sentence-1)
Template arguments can be explicitly specified when naming the function
template specialization, deduced from the context (e.g.,
deduced from the function arguments in a call to the function template
specialization, see [[temp.deduct]](temp.deduct "13.10.3Template argument deduction")), or obtained from default template arguments[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7535)
Each function template specialization instantiated from a template
has its own copy of any static variable[.](#2.sentence-1)
[*Example [1](#example-1)*: template<class T> void f(T* p) {static T s;};
void g(int a, char* b) { f(&a); // calls f<int>(int*) f(&b); // calls f<char*>(char**)}
Heref<int>(int*) has a static variables of typeint andf<char*>(char**) has a static variables of typechar*[.](#2.sentence-2)
— *end example*]

149
cppdraft/temp/friend.md Normal file
View File

@@ -0,0 +1,149 @@
[temp.friend]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.friend)
### 13.7.5 Friends [temp.friend]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3457)
A friend of a class or class template can be a function template or
class template, a specialization of a function template or class
template, or a non-template function or class[.](#1.sentence-1)
[*Example [1](#example-1)*: template<class T> class task;template<class T> task<T>* preempt(task<T>*);
template<class T> class task {friend void next_time(); friend void process(task<T>*); friend task<T>* preempt<T>(task<T>*); template<class C> friend int func(C); friend class task<int>; template<class P> friend class frd;};
Here,
each specialization of thetask class template has the functionnext_time as a friend;
becauseprocess does not have explicit[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s*,
each specialization of thetask class template has an appropriately typed functionprocess as a friend, and this friend is not a function template specialization;
because the friendpreempt has an explicit[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")T,
each specialization of thetask class template has the appropriate specialization of the function
templatepreempt as a friend;
and each specialization of thetask class template has all specializations of the function templatefunc as friends[.](#1.sentence-2)
Similarly,
each specialization of thetask class template has the class template specializationtask<int> as a friend, and has all specializations of the class templatefrd as friends[.](#1.sentence-3)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3519)
Friend classes, class templates, functions, or function templates
can be declared within a class template[.](#2.sentence-1)
When a template is instantiated,
its friend declarations are found by name lookup
as if the specialization had been explicitly declared at
its point of instantiation[.](#2.sentence-2)
[*Note [1](#note-1)*:
They can introduce entities
that belong to an enclosing namespace scope ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators")),
in which case they are attached to
the same module as the class template ([[module.unit]](module.unit "10.1Module units and purviews"))[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3533)
A friend template may be declared within a class or class template[.](#3.sentence-1)
A friend function template may be defined within a class or class
template, but a friend class template may not be defined in a class
or class template[.](#3.sentence-2)
In these cases, all specializations of the friend class or friend function
template are friends of the class or class template granting friendship[.](#3.sentence-3)
[*Example [2](#example-2)*: class A {template<class T> friend class B; // OKtemplate<class T> friend void f(T) { /* ... */ } // OK}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3549)
A template friend declaration specifies that all specializations of that
template, whether they are implicitly instantiated ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")), partially
specialized ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")) or explicitly specialized ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")),
are friends of the class containing the template friend declaration[.](#4.sentence-1)
[*Example [3](#example-3)*: class X {template<class T> friend struct A; class Y { };};
template<class T> struct A { X::Y ab; }; // OKtemplate<class T> struct A<T*> { X::Y ab; }; // OK — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3566)
A template friend declaration may declare
a member of a dependent type to be a friend[.](#5.sentence-1)
The friend declaration shall declare a function or
specify a type with an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]"),
in either case with a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") ending with a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]"), *C*,
whose [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") names a class template[.](#5.sentence-2)
The template parameters of the template friend declaration
shall be deducible from *C* ([[temp.deduct.type]](temp.deduct.type "13.10.3.6Deducing template arguments from a type"))[.](#5.sentence-3)
In this case,
a member of a specialization *S* of the class template
is a friend of the class granting friendship
if deduction of the template parameters
of *C* from *S* succeeds, and
substituting the deduced template arguments into the friend declaration
produces a declaration that corresponds to
the member of the specialization[.](#5.sentence-4)
[*Example [4](#example-4)*: template<class T> struct A {struct B { }; void f(); struct D {void g(); };
T h(); template<T U> T i();};template<> struct A<int> {struct B { }; int f(); struct D {void g(); }; template<int U> int i();};template<> struct A<float*> {int *h();};
class C {template<class T> friend struct A<T>::B; // grants friendship to A<int>::B even though// it is not a specialization of A<T>::Btemplate<class T> friend void A<T>::f(); // does not grant friendship to A<int>::f()// because its return type does not matchtemplate<class T> friend void A<T>::D::g(); // error: A<T>::D does not end with a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")template<class T> friend int *A<T*>::h(); // grants friendship to A<int*>::h() and A<float*>::h()template<class T> template<T U> // grants friendship to instantiations of A<T>::i() andfriend T A<T>::i(); // to A<int>::i(), and thereby to all specializations}; // of those function templates — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3620)
A friend template shall not be declared in a local class[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3623)
Friend declarations shall not declare partial specializations[.](#7.sentence-1)
[*Example [5](#example-5)*: template<class T> class A { };class X {template<class T> friend class A<T*>; // error}; — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3634)
When a friend declaration refers to a specialization of a function
template, the function parameter declarations shall not include
default arguments, nor shall
the inline, constexpr, or consteval specifiers
be used in such a declaration[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3641)
A non-template friend declaration
with a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") shall be a definition[.](#9.sentence-1)
A friend function template
with a constraint that depends on a template parameter from an enclosing template
shall be a definition[.](#9.sentence-2)
Such a constrained friend function or function template declaration
does not declare the same function or function template as a declaration in any other scope[.](#9.sentence-3)

253
cppdraft/temp/func/order.md Normal file
View File

@@ -0,0 +1,253 @@
[temp.func.order]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.func.order)
### 13.7.7 Function templates [[temp.fct]](temp.fct#temp.func.order)
#### 13.7.7.3 Partial ordering of function templates [temp.func.order]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4312)
If multiple function templates share a name,
the use of that name can be ambiguous because
template argument deduction ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) may identify
a specialization for more than one function template[.](#1.sentence-1)
[*Partial ordering*](#def:template,function,partial_ordering "13.7.7.3Partial ordering of function templates[temp.func.order]") of overloaded function template declarations is used in the following contexts
to select the function template to which a function template specialization
refers:
- [(1.1)](#1.1)
during overload resolution for a call to a function template specialization ([[over.match.best]](over.match.best "12.2.4Best viable function"));
- [(1.2)](#1.2)
when the address of a function template specialization is taken;
- [(1.3)](#1.3)
when a placement operator delete that is a
function template
specialization
is selected to match a placement operator new ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"), [[expr.new]](expr.new "7.6.2.8New"));
- [(1.4)](#1.4)
when a [friend function declaration](temp.friend "13.7.5Friends[temp.friend]"), an[explicit instantiation](temp.explicit "13.9.3Explicit instantiation[temp.explicit]") or an [explicit specialization](temp.expl.spec "13.9.4Explicit specialization[temp.expl.spec]") refers to
a function template specialization[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4339)
Partial ordering selects which of two function templates is more
specialized than the other by transforming each template in turn
(see next paragraph) and performing template argument deduction
using the function type[.](#2.sentence-1)
The deduction process determines whether
one of the templates is more specialized than the other[.](#2.sentence-2)
If so, the
more specialized template is the one chosen by the partial ordering
process[.](#2.sentence-3)
If both deductions succeed, the partial ordering selects
the more constrained template (if one exists) as determined below[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4351)
To produce the transformed template, for each
type, constant,
type template, variable template, or concept
template parameter (including template parameter packs ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))
thereof) synthesize a unique type, value, class template,
variable template, or concept,
respectively, and substitute it for each occurrence of that parameter
in the function type of the template[.](#3.sentence-1)
[*Note [1](#note-1)*:
The type replacing the placeholder
in the type of the value synthesized for a constant template parameter
is also a unique synthesized type[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4369)
A synthesized template has the same [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") as
its corresponding template template parameter[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4375)
Each function template M that is a member function
is considered to have
a new first parameter of type X(M), described below,
inserted in its function parameter list[.](#5.sentence-1)
If exactly one of the function templates was considered by overload resolution
via a rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions"))
with a reversed order of parameters,
then the order of the function parameters in its transformed template
is reversed[.](#5.sentence-2)
For a function template M with cv-qualifiers cv that is a member of a class A:
- [(5.1)](#5.1)
The type X(M) is “rvalue reference to cv A”
if the optional [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") ofM is && or
if M has no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") and
the positionally-corresponding parameter of the other transformed template
has rvalue reference type;
if this determination depends recursively upon
whether X(M) is an rvalue reference type,
it is not considered to have rvalue reference type[.](#5.1.sentence-1)
- [(5.2)](#5.2)
Otherwise, X(M) is “lvalue reference to cv A”[.](#5.2.sentence-1)
[*Note [2](#note-2)*:
This allows a non-static
member to be ordered with respect to a non-member function and for the results
to be equivalent to the ordering of two equivalent non-members[.](#5.sentence-4)
— *end note*]
[*Example [1](#example-1)*: struct A { };template<class T> struct B {template<class R> int operator*(R&); // #1};
template<class T, class R> int operator*(T&, R&); // #2// The declaration of B::operator* is transformed into the equivalent of// template<class R> int operator*(B<A>&, R&); // #1aint main() { A a;
B<A> b;
b * a; // calls #1} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4428)
Using the transformed function template's function type,
perform type deduction against the other template as described in [[temp.deduct.partial]](temp.deduct.partial "13.10.3.5Deducing template arguments during partial ordering")[.](#6.sentence-1)
[*Example [2](#example-2)*: template<class T> struct A { A(); };
template<class T> void f(T);template<class T> void f(T*);template<class T> void f(const T*);
template<class T> void g(T);template<class T> void g(T&);
template<class T> void h(const T&);template<class T> void h(A<T>&);
void m() {const int* p;
f(p); // f(const T*) is more specialized than f(T) or f(T*)float x;
g(x); // ambiguous: g(T) or g(T&) A<int> z;
h(z); // overload resolution selects h(A<T>&)const A<int> z2;
h(z2); // h(const T&) is called because h(A<T>&) is not callable} — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4459)
[*Note [3](#note-3)*:
Since, in a call context, such type deduction considers only parameters
for which there are explicit call arguments, some parameters are ignored (namely,
function parameter packs, parameters with default arguments, and ellipsis
parameters)[.](#7.sentence-1)
[*Example [3](#example-3)*: template<class T> void f(T); // #1template<class T> void f(T*, int=1); // #2template<class T> void g(T); // #3template<class T> void g(T*, ...); // #4int main() {int* ip;
f(ip); // calls #2 g(ip); // calls #4} — *end example*]
[*Example [4](#example-4)*: template<class T, class U> struct A { };
template<class T, class U> void f(U, A<U, T>* p = 0); // #1template< class U> void f(U, A<U, U>* p = 0); // #2template<class T > void g(T, T = T()); // #3template<class T, class... U> void g(T, U ...); // #4void h() { f<int>(42, (A<int, int>*)0); // calls #2 f<int>(42); // error: ambiguous g(42); // error: ambiguous} — *end example*]
[*Example [5](#example-5)*: template<class T, class... U> void f(T, U...); // #1template<class T > void f(T); // #2template<class T, class... U> void g(T*, U...); // #3template<class T > void g(T); // #4void h(int i) { f(&i); // OK, calls #2 g(&i); // OK, calls #3} — *end example*]
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4512)
If deduction against the other template succeeds for both transformed templates,
constraints can be considered as follows:
- [(8.1)](#8.1)
If their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* (possibly including [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* invented for an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))) or
function parameter lists differ in length,
neither template is more specialized than the other[.](#8.1.sentence-1)
- [(8.2)](#8.2)
Otherwise:
* [(8.2.1)](#8.2.1)
If exactly one of the templates was considered by overload resolution
via a rewritten candidate with reversed order of parameters:
+
[(8.2.1.1)](#8.2.1.1)
If, for either template, some of the template parameters
are not deducible from their function parameters,
neither template is more specialized than the other.
+
[(8.2.1.2)](#8.2.1.2)
If there is either no reordering or more than one reordering
of the associated [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") such that
- [(8.2.1.2.1)](#8.2.1.2.1)
the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* are equivalent and
- [(8.2.1.2.2)](#8.2.1.2.2)
the function parameters that positionally correspond
between the two templates are of the same type,
neither template is more specialized than the other.
* [(8.2.2)](#8.2.2)
Otherwise, if the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* are not equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading")) or
if the function parameters that positionally correspond
between the two templates are not of the same type,
neither template is more specialized than the other[.](#8.2.sentence-1)
- [(8.3)](#8.3)
Otherwise, if the context in which the partial ordering is done
is that of a call to a conversion function and
the return types of the templates are not the same,
then neither template is more specialized than the other[.](#8.3.sentence-1)
- [(8.4)](#8.4)
Otherwise,
if one template is more constrained than the other ([[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints")),
the more constrained template is more specialized than the other[.](#8.4.sentence-1)
- [(8.5)](#8.5)
Otherwise, neither template is more specialized than the other[.](#8.5.sentence-1)
[*Example [6](#example-6)*: template <typename> constexpr bool True = true;template <typename T> concept C = True<T>;
void f(C auto &, auto &) = delete;template <C Q> void f(Q &, C auto &);
void g(struct A *ap, struct B *bp) { f(*ap, *bp); // OK, can use different methods to produce template parameters}template <typename T, typename U> struct X {};
template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete;template <C T, C U, C V> bool operator==(T, X<U, V>);
void h() { X<void *, int>{} == 0; // OK, correspondence of [T, U, V] and [U, V, T]} — *end example*]

412
cppdraft/temp/inst.md Normal file
View 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.2Implicit instantiation[temp.inst]") if there is a reachable
explicit instantiation definition ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")) or
explicit specialization declaration ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit 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.7Placeholder type specifiers")),
- [(1.3)](#1.3)
a potentially-constant variable ([[expr.const]](expr.const "7.7Constant 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.7Program 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.2Matching of partial specializations"))
has been declared, but not defined,
at the point of instantiation ([[temp.point]](temp.point "13.8.4.1Point of instantiation")),
the instantiation yields an incomplete class type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General"))[.](#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.6Local 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.5Exception specifications[except.spec]")*s*, and non-static data member
initializers, if any,
but not their [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* or [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[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.5Exception 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.3One-definition rule") and [[class.mem]](class.mem "11.4Class 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.3One-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.7Constant 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.2Overload 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.4Overload 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.2The 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.4Compound 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.2Closure 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.2Implicit 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.5Exception specifications[except.spec]") and [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1General[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.5Exception specifications"), [[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#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.1Point 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.2Template parameters[temp.param]")*s* and [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[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.3Constrained declarations") and [[temp.constr.atomic]](temp.constr.atomic "13.5.2.3Atomic constraints") when determining whether the constraints are satisfied
or as specified in [[temp.constr.decl]](temp.constr.decl "13.5.3Constrained 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.3Template argument deduction")) and
overload resolution ([[over.match]](over.match "12.2Overload 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.2Default 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*]

118
cppdraft/temp/local.md Normal file
View File

@@ -0,0 +1,118 @@
[temp.local]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.local)
### 13.8.2 Locally declared names [temp.local]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5110)
Like normal (non-template) classes, class templates have an
injected-class-name ([[class.pre]](class.pre "11.1Preamble"))[.](#1.sentence-1)
The
injected-class-name can be used
as a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")[.](#1.sentence-2)
When it is used with a[*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]"),
as a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a type template template parameter,
or as the final identifier in the [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") of
a friend class template declaration,
it is a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") that refers to the
class template itself[.](#1.sentence-3)
Otherwise, it is a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") equivalent to the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") followed by
the template argument list ([[temp.decls.general]](temp.decls.general "13.7.1General"), [[temp.arg.general]](temp.arg.general "13.4.1General"))
of the class template
enclosed in <>[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5130)
When the injected-class-name of a class template specialization or
partial specialization is used as a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"),
it is equivalent to the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") followed by the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* of the class template specialization or partial
specialization enclosed in<>[.](#2.sentence-1)
[*Example [1](#example-1)*: template<template<class> class T> class A { };template<class T> class Y;template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<::Y>class B {template<class> friend class Y; // meaning ::Y};}; — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5153)
The injected-class-name of a class template or class
template specialization can be used as either
a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") wherever it is named[.](#3.sentence-1)
[*Example [2](#example-2)*: template <class T> struct Base { Base* p;};
template <class T> struct Derived: public Base<T> {typename Derived::Base* p; // meaning Derived::Base<T>};
template<class T, template<class> class U = T::Base> struct Third { };
Third<Derived<int> > t; // OK, default argument uses injected-class-name as a template — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5173)
A lookup that finds an injected-class-name ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) can result in an ambiguity in
certain cases (for example, if it is found in more than one
base class)[.](#4.sentence-1)
If all of the injected-class-names that are
found refer to specializations of the same class template,
and if the name
is used as a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]"),
the reference refers to the class template itself and not a
specialization thereof, and is not ambiguous[.](#4.sentence-2)
[*Example [3](#example-3)*: template <class T> struct Base { };template <class T> struct Derived: Base<int>, Base<char> {typename Derived::Base b; // error: ambiguoustypename Derived::Base<double> d; // OK}; — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5193)
When the normal name of the template (i.e., the name from
the enclosing scope, not the injected-class-name) is
used,
it always refers to the class template itself and not a
specialization of the template[.](#5.sentence-1)
[*Example [4](#example-4)*: template<class T> class X { X* p; // meaning X<T> X<T>* p2;
X<int>* p3; ::X* p4; // error: missing template argument list// ::X does not refer to the injected-class-name}; — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5211)
The name of a template parameter
shall not be bound to any following declaration
whose locus is contained by the scope
to which the template parameter belongs[.](#6.sentence-1)
[*Example [5](#example-5)*: template<class T, int i> class Y {int T; // error: template parameter hiddenvoid f() {char T; // error: template parameter hidden}friend void T(); // OK, no name bound};
template<class X> class X; // error: hidden by template parameter — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5230)
Unqualified name lookup considers
the template parameter scope of a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") immediately after the outermost scope associated with the template declared
(even if its parent scope does not contain
the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]"))[.](#7.sentence-1)
[*Note [1](#note-1)*:
The scope of a class template,
including its non-dependent base classes ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types"), [[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")),
is searched before its template parameter scope[.](#7.sentence-2)
— *end note*]
[*Example [6](#example-6)*: struct B { };namespace N {typedef void V; template<class T> struct A : B {typedef void C; void f(); template<class U> void g(U); };}template<class V> void N::A<V>::f() { // N::V not considered here V v; // V is still the template parameter, not N::V}template<class B> template<class C> void N::A<B>::g(C) { B b; // B is the base class, not the template parameter C c; // C is the template parameter, not A's C} — *end example*]

103
cppdraft/temp/mem.md Normal file
View File

@@ -0,0 +1,103 @@
[temp.mem]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.mem)
### 13.7.3 Member templates [temp.mem]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2951)
A template can be declared within a class or class template; such a template
is called a member template[.](#1.sentence-1)
A member template can be defined within or outside its class definition or
class template definition[.](#1.sentence-2)
A member template of a class template that is defined outside of its class
template definition shall be specified with
a [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") equivalent to that
of the class template followed by
a [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") equivalent to that
of the member template ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#1.sentence-3)
[*Example [1](#example-1)*: template<class T> struct string {template<class T2> int compare(const T2&); template<class T2> string(const string<T2>& s) { /* ... */ }};
template<class T> template<class T2> int string<T>::compare(const T2& s) {} — *end example*]
[*Example [2](#example-2)*: template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) <= 4;
template<C1 T> struct S {template<C2 U> void f(U); template<C2 U> void g(U);};
template<C1 T> template<C2 U>void S<T>::f(U) { } // OKtemplate<C1 T> template<typename U>void S<T>::g(U) { } // error: no matching function in S<T> — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2990)
A local class of non-closure type shall not have member templates[.](#2.sentence-1)
[Access control rules](class.access "11.8Member access control[class.access]") apply to member template names[.](#2.sentence-2)
A destructor shall not be a member
template[.](#2.sentence-3)
A non-template member function ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) with a given name
and type and a member function template of the same name, which could be
used to generate a specialization of the same type, can both be
declared in a class[.](#2.sentence-4)
When both exist, a use of that name and type refers to the
non-template member unless an explicit template argument list is supplied[.](#2.sentence-5)
[*Example [3](#example-3)*: template <class T> struct A {void f(int); template <class T2> void f(T2);};
template <> void A<int>::f(int) { } // non-template member functiontemplate <> template <> void A<int>::f<>(int) { } // member function template specializationint main() { A<char> ac;
ac.f(1); // non-template ac.f('c'); // template ac.f<>(1); // template} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3021)
A member function template shall not be declared virtual[.](#3.sentence-1)
[*Example [4](#example-4)*: template <class T> struct AA {template <class C> virtual void g(C); // errorvirtual void f(); // OK}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3032)
A specialization of
a member function template does not override a virtual function from a
base class[.](#4.sentence-1)
[*Example [5](#example-5)*: class B {virtual void f(int);};
class D : public B {template <class T> void f(T); // does not override B::f(int)void f(int i) { f<>(i); } // overriding function that calls the function template specialization}; — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3049)
[*Note [1](#note-1)*:
A specialization of a
conversion function template
is named in
the same way as a non-template conversion function that converts to
the same type ([[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions"))[.](#5.sentence-1)
[*Example [6](#example-6)*: struct A {template <class T> operator T*();};template <class T> A::operator T*() { return 0; }template <> A::operator char*() { return 0; } // specializationtemplate A::operator void*(); // explicit instantiationint main() { A a; int* ip;
ip = a.operator int*(); // explicit call to template operator A::operator int*()} — *end example*]
An expression designating
a particular specialization of a conversion function template
can only be formed with a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")[.](#5.sentence-2)
There is no analogous syntax to form a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") ([[temp.names]](temp.names "13.3Names of template specializations"))
for such a function
by providing an explicit template argument list ([[temp.arg.explicit]](temp.arg.explicit "13.10.2Explicit template argument specification"))[.](#5.sentence-3)
— *end note*]

View File

@@ -0,0 +1,27 @@
[temp.mem.class]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.mem.class)
### 13.7.2 Class templates [[temp.class]](temp.class#temp.mem.class)
#### 13.7.2.4 Member classes of class templates [temp.mem.class]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2880)
A member class of a class template may be defined outside the class template
definition in which it is declared[.](#1.sentence-1)
[*Note [1](#note-1)*:
The member class must be defined before its first use that requires
an instantiation ([[temp.inst]](temp.inst "13.9.2Implicit instantiation"))[.](#1.sentence-2)
For example,template<class T> struct A {class B;};
A<int>::B* b1; // OK, requires A to be defined but not A::Btemplate<class T> class A<T>::B { };
A<int>::B b2; // OK, requires A::B to be defined
— *end note*]

19
cppdraft/temp/mem/enum.md Normal file
View File

@@ -0,0 +1,19 @@
[temp.mem.enum]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.mem.enum)
### 13.7.2 Class templates [[temp.class]](temp.class#temp.mem.enum)
#### 13.7.2.6 Enumeration members of class templates [temp.mem.enum]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2936)
An enumeration member of a class template may be defined outside the class
template definition[.](#1.sentence-1)
[*Example [1](#example-1)*: template<class T> struct A {enum E : T;};template<class T> enum A<T>::E : T { e1, e2 };
A<int>::E e = A<int>::e1; — *end example*]

49
cppdraft/temp/mem/func.md Normal file
View File

@@ -0,0 +1,49 @@
[temp.mem.func]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.mem.func)
### 13.7.2 Class templates [[temp.class]](temp.class#temp.mem.func)
#### 13.7.2.2 Member functions of class templates [temp.mem.func]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2751)
A member function
of a class template
may be defined outside of the class
template definition in which it is declared[.](#1.sentence-1)
[*Example [1](#example-1)*: template<class T> class Array { T* v; int sz;public:explicit Array(int);
T& operator[](int);
T& elem(int i) { return v[i]; }};
declares three member functions of a class template[.](#1.sentence-2)
The subscript function can be defined like this:template<class T> T& Array<T>::operator[](int i) {if (i<0 || sz<=i) error("Array: range error"); return v[i];}
A constrained member function can be defined out of line:template<typename T> concept C = requires {typename T::type;};
template<typename T> struct S {void f() requires C<T>; void g() requires C<T>;};
template<typename T>void S<T>::f() requires C<T> { } // OKtemplate<typename T>void S<T>::g() { } // error: no matching function in S<T>
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2796)
The[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* for a member function of a class template are determined by the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* of the type of the object for which the member function is called[.](#2.sentence-1)
[*Example [2](#example-2)*:
The[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") forArray<T>::operator[] will be determined by theArray to which the subscripting operation is applied[.](#2.sentence-2)
Array<int> v1(20);
Array<dcomplex> v2(30);
v1[3] = 7; // Array<int>::operator[] v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[] — *end example*]

258
cppdraft/temp/names.md Normal file
View File

@@ -0,0 +1,258 @@
[temp.names]
# 13 Templates [[temp]](./#temp)
## 13.3 Names of template specializations [temp.names]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L688)
A [template specialization](temp.spec "13.9Template instantiation and specialization[temp.spec]") can be referred to by a[*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]"):
[simple-template-id:](#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[template-id:](#nt:template-id "13.3Names of template specializations[temp.names]")
[*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1General[over.oper.general]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6User-defined literals[over.literal]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[template-name:](#nt:template-name "13.3Names of template specializations[temp.names]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[template-argument-list:](#nt:template-argument-list "13.3Names of template specializations[temp.names]")
[*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") ...opt
[*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]") , [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") ...opt
[template-argument:](#nt:template-argument "13.3Names of template specializations[temp.names]")
[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L723)
The component name of a[*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]"),[*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]"), or[*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") is the first name in it[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L731)
A < is interpreted as the delimiter of
a [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]") if either
- [(3.1)](#3.1)
it follows a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") that either
* [(3.1.1)](#3.1.1)
appears in a type-only context or
* [(3.1.2)](#3.1.2)
is preceded by template or typename, or
- [(3.2)](#3.2)
it follows a name that is not a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") and
* [(3.2.1)](#3.2.1)
that follows the keyword template or a ~ after a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") or
in a class member access expression, or
* [(3.2.2)](#3.2.2)
for which name lookup finds the injected-class-name of a class template or
finds any declaration of a template, or
* [(3.2.3)](#3.2.3)
that is an unqualified name
for which name lookup either finds one or more functions or finds nothing, or
* [(3.2.4)](#3.2.4)
that is a terminal name
in a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10The using declaration")),
in a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators")), or
in a type-only context
other than a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") ([[temp.res]](temp.res "13.8Name resolution"))[.](#3.sentence-1)
[*Note [1](#note-1)*:
If the name is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"),
it is then interpreted as a [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]")[.](#3.sentence-2)
The keyword template is used to indicate
that a dependent qualified name ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types")) denotes a template
where an expression might appear[.](#3.sentence-3)
— *end note*]
[*Example [1](#example-1)*: struct X {template<std::size_t> X* alloc(); template<std::size_t> static X* adjust();};template<class T> void f(T* p) { T* p1 = p->alloc<200>(); // error: < means less than T* p2 = p->template alloc<200>(); // OK, < starts template argument list T::adjust<100>(); // error: < means less than T::template adjust<100>(); // OK, < starts template argument liststatic constexpr std::meta::info r = ^^T::adjust;
T* p3 = [:r:]<200>(); // error: < means less than T* p4 = template [:r:]<200>(); // OK, < starts template argument list}} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L789)
When parsing a [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]"),
the first non-nested>[108](#footnote-108 "A > that encloses the type-id of a dynamic_­cast, static_­cast, reinterpret_­cast or const_­cast, or which encloses the template-arguments of a subsequent template-id or splice-specialization-specifier, is considered nested for the purpose of this description.") is taken as the ending delimiter
rather than a greater-than operator[.](#4.sentence-1)
Similarly, the first non-nested >> is treated as two
consecutive but distinct > tokens, the first of which is taken
as the end of the [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]") and completes
the [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")[.](#4.sentence-2)
[*Note [2](#note-2)*:
The second > token produced by this replacement rule can terminate an enclosing[*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") construct or it can be part of a different construct (e.g., a cast)[.](#4.sentence-3)
— *end note*]
[*Example [2](#example-2)*: template<int i> class X { /* ... */ };
X< 1>2 > x1; // syntax error X<(1>2)> x2; // OKtemplate<class T> class Y { /* ... */ };
Y<X<1>> x3; // OK, same as Y<X<1> > x3; Y<X<6>>1>> x4; // syntax error Y<X<(6>>1)>> x5; // OK — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L828)
The keyword template shall not appear immediately after
a declarative [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L832)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") of a [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") shall not be an unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]")[.](#6.sentence-1)
[*Example [3](#example-3)*: template<int> struct S { };constexpr int k = 5;constexpr std::meta::info r = ^^k;
S<[:r:]> s1; // error: unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") used as template argument S<([:r:])> s2; // OK S<[:r:] + 1> s3; // OK — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L846)
A name prefixed by the keywordtemplate shall be followed by a template argument list or
refer to a class template or an alias template[.](#7.sentence-1)
The latter case is deprecated ([[depr.template.template]](depr.template.template "D.9template keyword before qualified names"))[.](#7.sentence-2)
The keyword template shall not appear immediately
before a ~ token (as to name a destructor)[.](#7.sentence-3)
[*Note [3](#note-3)*:
The keywordtemplate cannot be applied to non-template members of class templates[.](#7.sentence-4)
— *end note*]
[*Note [4](#note-4)*:
As is the case with thetypename prefix, thetemplate prefix is well-formed
even when lookup for the name would already find a template[.](#7.sentence-5)
— *end note*]
[*Example [4](#example-4)*: template <class T> struct A {void f(int); template <class U> void f(U);};
template <class T> void f(T t) { A<T> a;
a.template f<>(t); // OK, calls template a.template f(t); // error: not a [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]")}template <class T> struct B {template <class T2> struct C { };};
// deprecated: T::C is assumed to name a class template:template <class T, template <class X> class TT = T::template C> struct D { };
D<B<int> > db; — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L890)
A [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is [*valid*](#def:template-id,valid "13.3Names of template specializations[temp.names]") if
- [(8.1)](#8.1)
there are at most as many arguments as there are parameters
or a parameter is a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")),
- [(8.2)](#8.2)
there is an argument for each non-deducible non-pack parameter
that does not have a default [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]"),
- [(8.3)](#8.3)
each [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") matches the corresponding
template parameter ([[temp.arg]](temp.arg "13.4Template arguments")),
- [(8.4)](#8.4)
substitution of each template argument into the following
template parameters (if any) succeeds, and
- [(8.5)](#8.5)
if the [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is non-dependent,
the associated constraints are satisfied as specified in the next paragraph[.](#8.sentence-1)
A [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall be valid unless its respective[*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") names or designates a function template ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"))[.](#8.sentence-2)
[*Example [5](#example-5)*: template<class T, T::type n = 0> class X;struct S {using type = int;};using T1 = X<S, int, int>; // error: too many argumentsusing T2 = X<>; // error: no default argument for first template parameterusing T3 = X<1>; // error: value 1 does not match type-parameterusing T4 = X<int>; // error: substitution failure for second template parameterusing T5 = X<S>; // OK — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L934)
When the [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") of a [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") or
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") designates a constrained non-function template
or
a constrained template template parameter,
and
all [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]")*s* in the [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") are non-dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7Dependent template arguments")),
the associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
of the constrained template
shall be satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))[.](#9.sentence-1)
[*Example [6](#example-6)*: template<typename T> concept C1 = sizeof(T) != sizeof(int);
template<C1 T> struct S1 { };template<C1 T> using Ptr = T*;
S1<int>* p; // error: constraints not satisfied Ptr<int> p; // error: constraints not satisfiedtemplate<typename T>struct S2 { Ptr<int> x; }; // ill-formed, no diagnostic requiredtemplate<typename T>struct S3 { Ptr<T> x; }; // OK, satisfaction is not required S3<int> x; // error: constraints not satisfiedtemplate<template<C1 T> class X>struct S4 { X<int> x; // ill-formed, no diagnostic required};
template<typename T> concept C2 = sizeof(T) == 1;
template<C2 T> struct S { };
template struct S<char[2]>; // error: constraints not satisfiedtemplate<> struct S<char[2]> { }; // error: constraints not satisfied — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L982)
A [*concept-id*](#def:concept-id "13.3Names of template specializations[temp.names]") is a [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") where the [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") is a [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]")[.](#10.sentence-1)
A concept-id is a prvalue of type bool, and
does not name a template specialization[.](#10.sentence-2)
A concept-id evaluates to true if the concept's
normalized [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
is satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")) by the specified template arguments andfalse otherwise[.](#10.sentence-3)
[*Note [5](#note-5)*:
Since a [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is an unevaluated operand,
a concept-id appearing in a [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") is not evaluated except as necessary
to determine whether the normalized constraints are satisfied[.](#10.sentence-4)
— *end note*]
[*Example [7](#example-7)*: template<typename T> concept C = true;static_assert(C<int>); // OK — *end example*]
[108)](#footnote-108)[108)](#footnoteref-108)
A > that encloses the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]")*s* of a subsequent [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
is considered nested for the purpose of this description[.](#footnote-108.sentence-1)

113
cppdraft/temp/over.md Normal file
View File

@@ -0,0 +1,113 @@
[temp.over]
# 13 Templates [[temp]](./#temp)
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.over)
### 13.10.4 Overload resolution [temp.over]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9502)
When a call of a function or function template
is written (explicitly, or implicitly using the
operator notation), template argument deduction ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"))
and checking of any explicit template arguments ([[temp.arg]](temp.arg "13.4Template arguments")) are performed
for each function template to find the template argument values (if any) that
can be used with that function template to instantiate a function template
specialization that can be invoked with the call arguments or,
for conversion function templates, that can convert to the required type[.](#1.sentence-1)
For each function template:
- [(1.1)](#1.1)
If the argument deduction and checking succeeds, the[*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* (deduced and/or explicit)
are used to synthesize the declaration of
a single function template specialization which is
added to the candidate functions set to be used in overload resolution[.](#1.1.sentence-1)
- [(1.2)](#1.2)
If the argument deduction fails or
the synthesized function template specialization would be ill-formed,
no such function is added to the set of candidate functions for that template[.](#1.2.sentence-1)
The complete set of candidate functions includes all the synthesized
declarations and all of the non-template functions found by name lookup[.](#1.sentence-3)
The synthesized declarations are
treated like any other functions in
the remainder of overload resolution, except as explicitly noted
in [[over.match.best]](over.match.best "12.2.4Best viable function")[.](#1.sentence-4)[121](#footnote-121 "The parameters of function template specializations contain no template parameter types. The set of conversions allowed on deduced arguments is limited, because the argument deduction process produces function templates with parameters that either match the call arguments exactly or differ only in ways that can be bridged by the allowed limited conversions. Non-deduced arguments allow the full range of conversions. Note also that [over.match.best] specifies that a non-template function will be given preference over a template specialization if the two functions are otherwise equally good candidates for an overload match.")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9544)
[*Example [1](#example-1)*: template<class T> T max(T a, T b) { return a>b?a:b; }void f(int a, int b, char c, char d) {int m1 = max(a,b); // max(int a, int b)char m2 = max(c,d); // max(char a, char b)int m3 = max(a,c); // error: cannot generate max(int,char)}
Adding the non-template functionint max(int,int); to the example above would resolve the third call, by providing a function that
can be called formax(a,c) after using the standard conversion ofchar toint forc[.](#2.sentence-1)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9571)
[*Example [2](#example-2)*:
Here is an example involving conversions on a function argument involved in
template argument deduction:template<class T> struct B { /* ... */ };template<class T> struct D : public B<T> { /* ... */ };template<class T> void f(B<T>&);
void g(B<int>& bi, D<int>& di) { f(bi); // f(bi) f(di); // f((B<int>&)di)}
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9587)
[*Example [3](#example-3)*:
Here is an example involving conversions on a function argument not involved in
template argument deduction:template<class T> void f(T*,int); // #1template<class T> void f(T,char); // #2void h(int* pi, int i, char c) { f(pi,i); // #1: f<int>(pi,i) f(pi,c); // #2: f<int*>(pi,c) f(i,c); // #2: f<int>(i,c); f(i,i); // #2: f<int>(i,char(i))}
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9605)
Only the signature of a function template specialization is needed to enter the
specialization in a set of candidate functions[.](#5.sentence-1)
Therefore only the function template declaration is needed to resolve a call
for which a template specialization is a candidate[.](#5.sentence-2)
[*Example [4](#example-4)*: template<class T> void f(T); // declarationvoid g() { f("Annemarie"); // calls f<const char*>}
The call tof is well-formed even if the templatef is only declared and not defined at the point of the call[.](#5.sentence-3)
The program will be ill-formed unless a specialization forf<const char*> is explicitly instantiated in some translation unit ([[temp.pre]](temp.pre "13.1Preamble"))[.](#5.sentence-4)
— *end example*]
[121)](#footnote-121)[121)](#footnoteref-121)
The parameters of function template
specializations contain no
template parameter types[.](#footnote-121.sentence-1)
The set of conversions allowed on deduced arguments is limited, because the
argument deduction process produces function templates with parameters that
either match the call arguments exactly or differ only in ways that can be
bridged by the allowed limited conversions[.](#footnote-121.sentence-2)
Non-deduced arguments allow the full range of conversions[.](#footnote-121.sentence-3)
Note also that [[over.match.best]](over.match.best "12.2.4Best viable function") specifies that a non-template function will
be given preference over a template specialization if the two functions
are otherwise equally good candidates for an overload match[.](#footnote-121.sentence-4)

232
cppdraft/temp/over/link.md Normal file
View File

@@ -0,0 +1,232 @@
[temp.over.link]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.over.link)
### 13.7.7 Function templates [[temp.fct]](temp.fct#temp.over.link)
#### 13.7.7.2 Function template overloading [temp.over.link]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4084)
It is possible to overload function templates so that two different
function template specializations have the same type[.](#1.sentence-1)
[*Example [1](#example-1)*:
// translation unit 1:template<class T>void f(T*);void g(int* p) { f(p); // calls f<int>(int*)}
// translation unit 2:template<class T>void f(T);void h(int* p) { f(p); // calls f<int*>(int*)}
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4112)
Such specializations are distinct functions and do not violate the[one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4116)
The signature of a function template
is defined in [[intro.defs]](intro.defs "3Terms and definitions")[.](#3.sentence-1)
The names of the template parameters are significant only for establishing
the relationship between the template parameters and the rest of the
signature[.](#3.sentence-2)
[*Note [1](#note-1)*:
Two distinct function templates can have identical function return types and
function parameter lists, even if overload resolution alone cannot distinguish
them[.](#3.sentence-3)
template<class T> void f();template<int I> void f(); // OK, overloads the first template// distinguishable with an explicit template argument list — *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4134)
When an expression that references a template parameter is used in the
function parameter list or the return type in the declaration of a
function template, the expression that references the template
parameter is part of the signature of the function template[.](#4.sentence-1)
This is
necessary to permit a declaration of a function template in one
translation unit to be linked with another declaration of the function
template in another translation unit and, conversely, to ensure that
function templates that are intended to be distinct are not linked
with one another[.](#4.sentence-2)
[*Example [2](#example-2)*: template <int I, int J> A<I+J> f(A<I>, A<J>); // #1template <int K, int L> A<K+L> f(A<K>, A<L>); // same as #1template <int I, int J> A<I-J> f(A<I>, A<J>); // different from #1 — *end example*]
[*Note [2](#note-2)*:
Most expressions that use template parameters use constant template
parameters, but it is possible for an expression to reference a type
parameter[.](#4.sentence-3)
For example, a template type parameter can be used in thesizeof operator[.](#4.sentence-4)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4160)
Two expressions involving template parameters are considered[*equivalent*](#def:equivalent,expressions "13.7.7.2Function template overloading[temp.over.link]") if two function definitions containing the expressions would satisfy
the [one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]"), except that the tokens used
to name the template parameters may differ as long as a token used to
name a template parameter in one expression is replaced by another token
that names the same template parameter in the other expression[.](#5.sentence-1)
Two unevaluated operands that do not involve template parameters
are considered equivalent
if two function definitions containing the expressions
would satisfy the one-definition rule,
except that the tokens used to name types and declarations may differ
as long as they name the same entities, and
the tokens used to form concept-ids ([[temp.names]](temp.names "13.3Names of template specializations")) may differ
as long as the two [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")*s* are the same ([[temp.type]](temp.type "13.6Type equivalence"))[.](#5.sentence-2)
[*Note [3](#note-3)*:
For instance, A<42> and A<40+2> name the same type[.](#5.sentence-3)
— *end note*]
Two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* are never considered equivalent[.](#5.sentence-4)
[*Note [4](#note-4)*:
The intent is to avoid [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* appearing in the
signature of a function template with external linkage[.](#5.sentence-5)
— *end note*]
For determining whether two dependent names ([[temp.dep]](temp.dep "13.8.3Dependent names")) are equivalent,
only the name itself is considered, not the result of name lookup[.](#5.sentence-6)
[*Note [5](#note-5)*:
If such a dependent name is unqualified,
it is looked up from
a first declaration of the function template ([[temp.res.general]](temp.res.general "13.8.1General"))[.](#5.sentence-7)
— *end note*]
[*Example [3](#example-3)*: template <int I, int J> void f(A<I+J>); // #1template <int K, int L> void f(A<K+L>); // same as #1template <class T> decltype(g(T())) h();int g(int);template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup…{ return g(T()); } // … although the lookup here does find g(int)int i = h<int>(); // template argument substitution fails; g(int)// not considered at the first declaration of h()// ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalenttemplate <int N> void foo(const char (*s)[([]{}, N)]);template <int N> void foo(const char (*s)[([]{}, N)]);
// two different declarations because the non-dependent portions are not considered equivalenttemplate <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]); — *end example*]
Two potentially-evaluated expressions involving template parameters that are not equivalent are[*functionally equivalent*](#def:functionally_equivalent,expressions "13.7.7.2Function template overloading[temp.over.link]") if, for any given set of template arguments, the evaluation of the
expression results in the same value[.](#5.sentence-8)
Two unevaluated operands that are not equivalent
are functionally equivalent if, for any given set of template arguments,
the expressions perform
the same operations in the same order with the same entities[.](#5.sentence-9)
[*Note [6](#note-6)*:
For instance, one could have redundant parentheses[.](#5.sentence-10)
— *end note*]
[*Example [4](#example-4)*: template<int I> concept C = true;template<typename T> struct A {void f() requires C<42>; // #1void f() requires true; // OK, different functions}; — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4235)
Two [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2Function template overloading[temp.over.link]") if
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* have the same length,
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are equivalent
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* that are equivalent
if either [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"),
and if either [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"),
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")*s* are equivalent[.](#6.sentence-1)
Two [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2Function template overloading[temp.over.link]") under the following conditions:
- [(6.1)](#6.1)
they declare template parameters of the same kind,
- [(6.2)](#6.2)
if either declares a template parameter pack, they both do,
- [(6.3)](#6.3)
if they declare constant template parameters,
they have equivalent types
ignoring the use of [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* for placeholder types, and
- [(6.4)](#6.4)
if they declare template template parameters,
their [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are equivalent[.](#6.sentence-2)
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")*s* are equivalent, the rules above are used to compare expressions
involving template parameters[.](#6.sentence-3)
Two [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2Function template overloading[temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))
the same set of template argument lists[.](#6.sentence-4)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4267)
If the validity or meaning of the program depends on
whether two constructs are equivalent, and they are
functionally equivalent but not equivalent, the program is ill-formed,
no diagnostic required[.](#7.sentence-1)
Furthermore, if two declarations A and B of function templates
- [(7.1)](#7.1)
introduce the same name,
- [(7.2)](#7.2)
have corresponding signatures ([[basic.scope.scope]](basic.scope.scope "6.4.1General")),
- [(7.3)](#7.3)
would declare the same entity,
when considering A and B to correspond in that determination ([[basic.link]](basic.link "6.7Program and linkage")), and
- [(7.4)](#7.4)
accept and are satisfied by the same set of template argument lists,
but do not correspond,
the program is ill-formed, no diagnostic required[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4287)
[*Note [7](#note-7)*:
This rule guarantees that equivalent declarations will be linked with
one another, while not requiring implementations to use heroic efforts
to guarantee that functionally equivalent declarations will be treated
as distinct[.](#8.sentence-1)
For example, the last two declarations are functionally
equivalent and would cause a program to be ill-formed:// guaranteed to be the sametemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);
// guaranteed to be differenttemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+11>);
// ill-formed, no diagnostic requiredtemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+1+2+3+4>);
— *end note*]

424
cppdraft/temp/param.md Normal file
View File

@@ -0,0 +1,424 @@
[temp.param]
# 13 Templates [[temp]](./#temp)
## 13.2 Template parameters [temp.param]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L234)
The syntax for[*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]")*s* is:
[template-parameter:](#nt:template-parameter "13.2Template parameters[temp.param]")
[*type-parameter*](#nt:type-parameter "13.2Template parameters[temp.param]")
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[*type-tt-parameter*](#nt:type-tt-parameter "13.2Template parameters[temp.param]")
[*variable-tt-parameter*](#nt:variable-tt-parameter "13.2Template parameters[temp.param]")
[*concept-tt-parameter*](#nt:concept-tt-parameter "13.2Template parameters[temp.param]")
[type-parameter:](#nt:type-parameter "13.2Template parameters[temp.param]")
[*type-parameter-key*](#nt:type-parameter-key "13.2Template parameters[temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt
[*type-parameter-key*](#nt:type-parameter-key "13.2Template parameters[temp.param]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt = [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
[*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt
[*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt = [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
[type-parameter-key:](#nt:type-parameter-key "13.2Template parameters[temp.param]")
class
typename
[type-constraint:](#nt:type-constraint "13.2Template parameters[temp.param]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") < [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[type-tt-parameter:](#nt:type-tt-parameter "13.2Template parameters[temp.param]")
[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") [*type-parameter-key*](#nt:type-parameter-key "13.2Template parameters[temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt
[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") [*type-parameter-key*](#nt:type-parameter-key "13.2Template parameters[temp.param]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt [*type-tt-parameter-default*](#nt:type-tt-parameter-default "13.2Template parameters[temp.param]")
[type-tt-parameter-default:](#nt:type-tt-parameter-default "13.2Template parameters[temp.param]")
= [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")
= [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")
[variable-tt-parameter:](#nt:variable-tt-parameter "13.2Template parameters[temp.param]")
[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") auto ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt
[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]") auto [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt = [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")
[concept-tt-parameter:](#nt:concept-tt-parameter "13.2Template parameters[temp.param]")
template < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") > concept ...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt
template < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") > concept [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt = [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")
The component names of a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") are
its [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") (if any)[.](#1.sentence-2)
[*Note [1](#note-1)*:
The > token following the[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") of a[*type-tt-parameter*](#nt:type-tt-parameter "13.2Template parameters[temp.param]"),[*variable-tt-parameter*](#nt:variable-tt-parameter "13.2Template parameters[temp.param]"), or[*concept-tt-parameter*](#nt:concept-tt-parameter "13.2Template parameters[temp.param]") can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3Names of template specializations"))[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L306)
A template parameter is of one of the following kinds:
- [(2.1)](#2.1)
A [*type template parameter*](#def:template_parameter,type "13.2Template parameters[temp.param]") is
a template parameter introduced by a [*type-parameter*](#nt:type-parameter "13.2Template parameters[temp.param]")[.](#2.1.sentence-1)
- [(2.2)](#2.2)
A [*constant template parameter*](#def:template_parameter,constant "13.2Template parameters[temp.param]") is
a template parameter introduced by a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#2.2.sentence-1)
- [(2.3)](#2.3)
A [*type template template parameter*](#def:template_parameter,type_template "13.2Template parameters[temp.param]") is
a template parameter introduced by a [*type-tt-parameter*](#nt:type-tt-parameter "13.2Template parameters[temp.param]")[.](#2.3.sentence-1)
- [(2.4)](#2.4)
A [*variable template template parameter*](#def:template_parameter,variable_template "13.2Template parameters[temp.param]") is
a template parameter introduced by a [*variable-tt-parameter*](#nt:variable-tt-parameter "13.2Template parameters[temp.param]")[.](#2.4.sentence-1)
- [(2.5)](#2.5)
A [*concept template parameter*](#def:template_parameter,concept "13.2Template parameters[temp.param]") is
a template parameter introduced by a [*concept-tt-parameter*](#nt:concept-tt-parameter "13.2Template parameters[temp.param]")[.](#2.5.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L329)
Type template template parameters,
variable template template parameters, and
concept template parameters
are collectively referred to as [*template template parameters*](#def:template_parameters,template "13.2Template parameters[temp.param]")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L335)
The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]"),
if any, shall not be dependent[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L339)
A concept template parameter shall not have
associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L343)
If a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") is
a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") that declares a pack ([[dcl.fct]](dcl.fct "9.3.4.6Functions")), or
otherwise has an ellipsis prior to its optional [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"),
then the [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") declares a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#6.sentence-1)
A template parameter pack that is a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") whose type
contains one or more unexpanded packs is a pack expansion[.](#6.sentence-2)
Similarly,
a template parameter pack that is a template template parameter with a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") containing one or more unexpanded
packs is a pack expansion[.](#6.sentence-3)
A type parameter pack with a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") that
contains an unexpanded parameter pack is a pack expansion[.](#6.sentence-4)
A template parameter pack that is a pack
expansion shall not expand a template parameter pack declared in the same[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")[.](#6.sentence-5)
[*Example [1](#example-1)*: template <class... Types> // Types is a template type parameter packclass Tuple; // but not a pack expansiontemplate <class T, int... Dims> // Dims is a constant template parameter packstruct multi_array; // but not a pack expansiontemplate <class... T>struct value_holder {template <T... Values> struct apply { }; // Values is a constant template parameter pack}; // and a pack expansiontemplate <class... T, T... Values> // error: Values expands template type parameterstruct static_array; // pack T within the same template parameter list — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L377)
There is no semantic difference betweenclass andtypename in a[*type-parameter-key*](#nt:type-parameter-key "13.2Template parameters[temp.param]")[.](#7.sentence-1)
typename followed by an[*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") names a template type parameter[.](#7.sentence-2)
typename followed by a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") denotes the type in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#7.sentence-3)
A [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") of the formclass [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is a [*type-parameter*](#nt:type-parameter "13.2Template parameters[temp.param]")[.](#7.sentence-4)
[*Example [2](#example-2)*: class T { /* ... */ };int i;
template<class T, T i> void f(T t) { T t1 = i; // template parameters T and i::T t2 = ::i; // global namespace members T and i}
Here, the template f has a type template parameter
called T, rather than an unnamed constant
template parameter of class T[.](#7.sentence-5)
— *end example*]
The [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") shall not have a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#7.sentence-6)
Types shall not be defined in a template parameter
declaration[.](#7.sentence-7)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L414)
The [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in
a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") denoting a type or template
is not looked up[.](#8.sentence-1)
An [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") that does not follow an ellipsis
is defined to be
- [(8.1)](#8.1)
a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") for a [*type-parameter*](#nt:type-parameter "13.2Template parameters[temp.param]"),
- [(8.2)](#8.2)
a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") for a [*variable-tt-parameter*](#nt:variable-tt-parameter "13.2Template parameters[temp.param]"),
- [(8.3)](#8.3)
a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") for a [*type-tt-parameter*](#nt:type-tt-parameter "13.2Template parameters[temp.param]"), or
- [(8.4)](#8.4)
a [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept definitions[temp.concept]") for a [*concept-tt-parameter*](#nt:concept-tt-parameter "13.2Template parameters[temp.param]"),
in the scope of the template declaration[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L432)
A [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") Q that designates a concept C can be used to constrain a
contextually-determined type or template type parameter pack T with a [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") E defined as follows[.](#9.sentence-1)
If Q is of the form C<A1, …, An>,
then let E′ be C<T, A1, …, An>[.](#9.sentence-2)
Otherwise, let E′ be C<T>[.](#9.sentence-3)
If T is not a pack,
then E is E′,
otherwise E is (E′ && ...)[.](#9.sentence-4)
This [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") E is called the[*immediately-declared constraint*](#def:constraint,immediately-declared "13.2Template parameters[temp.param]") of Q for T[.](#9.sentence-5)
The concept designated by a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") shall be a type concept ([[temp.concept]](temp.concept "13.7.9Concept definitions"))[.](#9.sentence-6)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L449)
A [*type-parameter*](#nt:type-parameter "13.2Template parameters[temp.param]") that starts with a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") introduces the immediately-declared constraint
of the [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") for the parameter[.](#10.sentence-1)
[*Example [3](#example-3)*: template<typename T> concept C1 = true;template<typename... Ts> concept C2 = true;template<typename T, typename U> concept C3 = true;
template<C1 T> struct s1; // associates C1<T>template<C1... T> struct s2; // associates (C1<T> && ...)template<C2... T> struct s3; // associates (C2<T> && ...)template<C3<int> T> struct s4; // associates C3<T, int>template<C3<int>... T> struct s5; // associates (C3<T, int> && ...) — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L467)
A constant template parameter
shall have one of the following (possibly cv-qualified) types:
- [(11.1)](#11.1)
a structural type (see below),
- [(11.2)](#11.2)
a type that contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")), or
- [(11.3)](#11.3)
a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"))[.](#11.sentence-1)
The top-level[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* on the[*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") are ignored when determining its type[.](#11.sentence-2)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L481)
A [*structural type*](#def:type,structural "13.2Template parameters[temp.param]") is one of the following:
- [(12.1)](#12.1)
a scalar type, or
- [(12.2)](#12.2)
an lvalue reference type, or
- [(12.3)](#12.3)
a literal class type with the following properties:
* [(12.3.1)](#12.3.1)
all base classes and non-static data members are public and non-mutable and
* [(12.3.2)](#12.3.2)
the types of all base classes and non-static data members are
structural types or (possibly multidimensional) arrays thereof[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L497)
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") naming
a constant template parameter of class type T denotes a static storage duration object of type const T,
known as a [*template parameter object*](#def:template_parameter_object "13.2Template parameters[temp.param]"),
which is template-argument-equivalent ([[temp.type]](temp.type "13.6Type equivalence")) to
the corresponding template argument
after it has been converted
to the type of the template parameter ([[temp.arg.nontype]](temp.arg.nontype "13.4.3Constant template arguments"))[.](#13.sentence-1)
No two template parameter objects are template-argument-equivalent[.](#13.sentence-2)
[*Note [2](#note-2)*:
If an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") names
a non-reference constant template parameter,
then it is a prvalue if it has non-class type[.](#13.sentence-3)
Otherwise, if it is of class type T,
it is an lvalue and has type const T ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#13.sentence-4)
— *end note*]
[*Example [4](#example-4)*: using X = int;struct A {};template<const X& x, int i, A a> void f() { i++; // error: change of template parameter value&x; // OK&i; // error: address of non-reference template parameter&a; // OKint& ri = i; // error: attempt to bind non-const reference to temporaryconst int& cri = i; // OK, const reference binds to temporaryconst A& ra = a; // OK, const reference binds to a template parameter object} — *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L531)
[*Note [3](#note-3)*:
A constant template parameter
cannot be declared to have type cv void[.](#14.sentence-1)
[*Example [5](#example-5)*: template<void v> class X; // errortemplate<void* pv> class Y; // OK — *end example*]
— *end note*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L543)
A constant template parameterof type “array of T” orof function type T is adjusted to be of type “pointer to T”[.](#15.sentence-1)
[*Example [6](#example-6)*: template<int* a> struct R { /* ... */ };template<int b[5]> struct S { /* ... */ };int p;
R<&p> w; // OK S<&p> x; // OK due to parameter adjustmentint v[5];
R<v> y; // OK due to implicit argument conversion S<v> z; // OK due to both adjustment and conversion — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L563)
A constant template parameter declared with a type that
contains a placeholder type with a [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") introduces the immediately-declared constraint
of the [*type-constraint*](#nt:type-constraint "13.2Template parameters[temp.param]") for the invented type corresponding to the placeholder ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#16.sentence-1)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L570)
A [*default template argument*](#def:template_argument,default "13.2Template parameters[temp.param]") is
a template argument ([[temp.arg]](temp.arg "13.4Template arguments")) specified after = in a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]")[.](#17.sentence-1)
A default template argument may be specified for
any kind of template parameter
that is not a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#17.sentence-2)
A default template argument may be specified in a template declaration[.](#17.sentence-3)
A default template argument shall not be specified in
the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]")*s* of the definition of a member of a class template
that appears outside of the member's class[.](#17.sentence-4)
A default template argument
shall not be specified in a friend class template declaration[.](#17.sentence-5)
If a friend function template declaration D specifies a default template argument,
that declaration shall be a definition and
there shall be no other declaration of the function template
which is reachable from D or from which D is reachable[.](#17.sentence-6)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L590)
The set of default template arguments
available for use is obtained by merging the default arguments
from all prior declarations of the template in the
same way default function arguments are ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#18.sentence-1)
[*Example [7](#example-7)*:
template<class T1, class T2 = int> class A;template<class T1 = int, class T2> class A; is equivalent totemplate<class T1 = int, class T2 = int> class A;
— *end example*]
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L606)
If a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") of a class template, variable template, or alias template has
a default template argument,
each subsequent [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") shall either have a default template argument supplied or
declare a template parameter pack[.](#19.sentence-1)
If a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") of
a primary class template, primary variable template, or alias template
declares a template parameter pack,
it shall be the last [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]")[.](#19.sentence-2)
If a [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") of a function template
declares a template parameter pack, it
shall not be followed by another [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") unless that template parameter is deducible from the
parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the function template or
has a default argument ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"))[.](#19.sentence-3)
A template parameter of a deduction guide template ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3Deduction guides"))
that does not have a default argument shall be deducible
from the parameter-type-list of the deduction guide template[.](#19.sentence-4)
[*Example [8](#example-8)*: template<class T1 = int, class T2> class B; // error// U can be neither deduced from the parameter-type-list nor specifiedtemplate<class... T, class... U> void f() { } // errortemplate<class... T, class U> void g() { } // error — *end example*]
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L637)
When parsing a default template argument
for a constant template parameter,
the first non-nested > is taken as
the end of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") rather than a greater-than operator[.](#20.sentence-1)
[*Example [9](#example-9)*: template<int i = 3 > 4 > // syntax errorclass X { /* ... */ };
template<int i = (3 > 4) > // OKclass Y { /* ... */ }; — *end example*]
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L653)
A [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") of
a template [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") is permitted to have a default template argument[.](#21.sentence-1)
When such default arguments are specified,
they apply to the template [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]") in the scope of the template [*template-parameter*](#nt:template-parameter "13.2Template parameters[temp.param]")[.](#21.sentence-2)
[*Example [10](#example-10)*: template <template <class TT = float> class T> struct A {inline void f(); inline void g();};template <template <class TT> class T> void A<T>::f() { T<> t; // error: TT has no default template argument}template <template <class TT = char> class T> void A<T>::g() { T<> t; // OK, T<char>} — *end example*]
The associated constraints of a template template parameter
shall not contain a concept-dependent constraint ([[temp.constr.concept]](temp.constr.concept "13.5.2.4Concept-dependent constraints"))[.](#21.sentence-3)
[*Example [11](#example-11)*: template<template<typename> concept C, template<C> class TT // error: C forms a concept-dependent constraint>struct A {}; — *end example*]

131
cppdraft/temp/point.md Normal file
View File

@@ -0,0 +1,131 @@
[temp.point]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#temp.point)
### 13.8.4 Dependent name resolution [[temp.dep.res]](temp.dep.res#temp.point)
#### 13.8.4.1 Point of instantiation [temp.point]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6073)
For a function template specialization, a member function template
specialization, or a specialization for a member function or static data member
of a class template,
if the specialization is implicitly instantiated because it is referenced
from within another template specialization and
the context from which it is referenced depends on a template parameter,
the point of instantiation of the specialization is the point of instantiation
of the enclosing specialization[.](#1.sentence-1)
Otherwise, the point of instantiation for such a specialization immediately
follows the namespace scope declaration
or definition that refers to the specialization[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6087)
If a function template or member function of a class template is called
in a way which uses the definition of a default argument of that function
template or member function,
the point of instantiation of the default argument is the point of
instantiation of the function template or member function specialization[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6094)
For a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") of a function template
specialization or specialization of a member function of a class template, if
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") is implicitly instantiated because
it is needed by another template specialization and the context that requires
it depends on a template parameter, the point of instantiation of the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") is the point of instantiation of the
specialization that requires it[.](#3.sentence-1)
Otherwise, the point of instantiation for such
a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") immediately follows the namespace
scope declaration or definition that requires the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6106)
For a class template specialization, a class member template specialization,
or a specialization for a class member of a class template,
if the specialization is implicitly instantiated because it is referenced
from within another template specialization,
if the context from which the specialization is referenced depends on a
template parameter,
and if the specialization is not instantiated previous to the instantiation of
the enclosing template,
the point of instantiation is immediately before the point of instantiation of
the enclosing template[.](#4.sentence-1)
Otherwise, the point of instantiation for such a specialization immediately
precedes the namespace scope declaration
or definition that refers to the specialization[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6121)
If a virtual function is implicitly instantiated, its point of instantiation
is immediately following the point of instantiation of its enclosing class
template specialization[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6126)
An explicit instantiation definition is an instantiation
point for the specialization or specializations specified by the explicit
instantiation[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6131)
A specialization for a function template, a member function template,
or of a member function or static data member of a class template may have
multiple points of instantiations within a translation unit, and in addition
to the points of instantiation described above,
- [(7.1)](#7.1)
for any such
specialization that has a point of instantiation within the[*declaration-seq*](dcl.pre#nt:declaration-seq "9.1Preamble[dcl.pre]") of the[*translation-unit*](basic.link#nt:translation-unit "6.7Program and linkage[basic.link]"),
prior to the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]") (if any),
the point after the [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1Preamble[dcl.pre]") of the [*translation-unit*](basic.link#nt:translation-unit "6.7Program and linkage[basic.link]") is also considered a point of instantiation,
and
- [(7.2)](#7.2)
for any such specialization that has a point of instantiation
within the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]"),
the end of the translation unit is also
considered a point of instantiation[.](#7.sentence-1)
A specialization for a class template has at most one point of instantiation
within a translation unit[.](#7.sentence-2)
A specialization for any template may have points of instantiation in multiple
translation units[.](#7.sentence-3)
If two different points of instantiation give a template specialization
different meanings according to the [one-definition rule](basic.def.odr "6.3One-definition rule[basic.def.odr]"),
the program is ill-formed, no diagnostic required[.](#7.sentence-4)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6161)
For the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements")),
the point of instantiation is the point of instantiation
of its enclosing templated entity, if any[.](#8.sentence-1)
Otherwise, it immediately follows the namespace-scope declaration
or definition that contains the expansion statement[.](#8.sentence-2)

241
cppdraft/temp/pre.md Normal file
View File

@@ -0,0 +1,241 @@
[temp.pre]
# 13 Templates [[temp]](./#temp)
## 13.1 Preamble [temp.pre]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L12)
A [*template*](#def:template "13.1Preamble[temp.pre]") defines a family of classes, functions, or variables,
an alias for a family of types, or a concept[.](#1.sentence-1)
[template-declaration:](#nt:template-declaration "13.1Preamble[temp.pre]")
[*template-head*](#nt:template-head "13.1Preamble[temp.pre]") [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")
[*template-head*](#nt:template-head "13.1Preamble[temp.pre]") [*concept-definition*](temp.concept#nt:concept-definition "13.7.9Concept definitions[temp.concept]")
[template-head:](#nt:template-head "13.1Preamble[temp.pre]")
template < [*template-parameter-list*](#nt:template-parameter-list "13.1Preamble[temp.pre]") > [*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]")opt
[template-parameter-list:](#nt:template-parameter-list "13.1Preamble[temp.pre]")
[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")
[*template-parameter-list*](#nt:template-parameter-list "13.1Preamble[temp.pre]") , [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")
[requires-clause:](#nt:requires-clause "13.1Preamble[temp.pre]")
requires [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]")
[constraint-logical-or-expression:](#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]")
[*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1Preamble[temp.pre]")
[*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]") || [*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1Preamble[temp.pre]")
[constraint-logical-and-expression:](#nt:constraint-logical-and-expression "13.1Preamble[temp.pre]")
[*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1Grammar[expr.prim.grammar]")
[*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1Preamble[temp.pre]") && [*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1Grammar[expr.prim.grammar]")
[*Note [1](#note-1)*:
The > token following the[*template-parameter-list*](#nt:template-parameter-list "13.1Preamble[temp.pre]") of a[*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]") can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3Names of template specializations"))[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L61)
The [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in a [*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]") (if any)
shall
- [(2.1)](#2.1)
declare or define a function, a class, or a variable, or
- [(2.2)](#2.2)
define a member function, a member class, a member enumeration, or a static data member of a
class template or of a class nested within a class template, or
- [(2.3)](#2.3)
define a member template of a class or class template, or
- [(2.4)](#2.4)
be a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]"), or
- [(2.5)](#2.5)
be a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]"), or
- [(2.6)](#2.6)
be an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L79)
A [*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]") is a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]")[.](#3.sentence-1)
A declaration introduced by a template declaration of avariable is a [*variable template*](#def:template,variable "13.1Preamble[temp.pre]")[.](#3.sentence-2)
A variable template at class scope is a[*static data member template*](#def:template,static_data_member "13.1Preamble[temp.pre]")[.](#3.sentence-3)
[*Example [1](#example-1)*: template<class T>constexpr T pi = T(3.1415926535897932385L);template<class T> T circular_area(T r) {return pi<T> * r * r; }struct matrix_constants {template<class T>using pauli = hermitian_matrix<T, 2>; template<class T>constexpr static pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } }; template<class T>constexpr static pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } }; template<class T>constexpr static pauli<T> sigma3 = { { 1, 0 }, { 0, -1 } };}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L107)
[*Note [2](#note-2)*:
A [*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]") can appear only as a namespace scope or class scope declaration[.](#4.sentence-1)
— *end note*]
Its [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") shall not be an[*export-declaration*](module.interface#nt:export-declaration "10.2Export declaration[module.interface]")[.](#4.sentence-2)
In a function template declaration, the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") shall be a name[.](#4.sentence-3)
[*Note [3](#note-3)*:
A class or variable template declaration of a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") declares a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"))[.](#4.sentence-4)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L121)
In a[*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]"),
explicit specialization, or explicit instantiation, the[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") in the declaration shall contain at most one declarator[.](#5.sentence-1)
When such a declaration is used to declare a class template,
no declarator is permitted[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L130)
A specialization (explicit or implicit) of one template is
distinct from all specializations of any other template[.](#6.sentence-1)
A template, an explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")), and a
partial specialization shall not have C language linkage[.](#6.sentence-2)
[*Note [4](#note-4)*:
Default arguments for function templates and for member functions of
class templates are considered definitions for the purpose of template
instantiation ([[temp.decls]](temp.decls "13.7Template declarations")) and must obey the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#6.sentence-3)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L142)
[*Note [5](#note-5)*:
A template cannot have the same name as any other
name bound in the same scope ([[basic.scope.scope]](basic.scope.scope "6.4.1General")), except
that a function template can share a name with [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]")*s*,
a type, non-template functions ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) and/or function templates ([[temp.over]](temp.over "13.10.4Overload resolution"))[.](#7.sentence-1)
Specializations, including partial specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")),
do not reintroduce or bind names[.](#7.sentence-2)
Their target scope is the target scope of the primary template,
so all specializations of a template belong to the same scope as it does[.](#7.sentence-3)
[*Example [2](#example-2)*: void f() {}class f {}; // OKnamespace N {void f(int) {}}using N::f; // OKtemplate<typename> void f(long) {} // #1, OKtemplate<typename> void f(long) {} // error: redefinition of #1template<typename> void f(long long) {} // OKtemplate<> void f<int>(long long) {} // OK, doesn't bind a name — *end example*]
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L168)
An entity is [*templated*](#def:templated "13.1Preamble[temp.pre]") if it is
- [(8.1)](#8.1)
a template,
- [(8.2)](#8.2)
an entity defined ([[basic.def]](basic.def "6.2Declarations and definitions")) or created ([[class.temporary]](class.temporary "6.8.7Temporary objects"))
within the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements")),
- [(8.3)](#8.3)
an entity defined or created in a templated entity,
- [(8.4)](#8.4)
a member of a templated entity,
- [(8.5)](#8.5)
an enumerator for an enumeration that is a templated entity, or
- [(8.6)](#8.6)
the closure type of a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types"))
appearing in the declaration of a templated entity[.](#8.sentence-1)
[*Note [6](#note-6)*:
A local class, a local or block variable, or a friend function defined in a
templated entity is a templated entity[.](#8.sentence-2)
— *end note*]
A [*templated function*](#def:function,templated "13.1Preamble[temp.pre]") is
a function template or a function that is templated[.](#8.sentence-3)
A [*templated class*](#def:class,templated "13.1Preamble[temp.pre]") is
a class template or a class that is templated[.](#8.sentence-4)
A [*templated variable*](#def:variable,templated "13.1Preamble[temp.pre]") is
a variable template or a variable that is templated[.](#8.sentence-5)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L196)
A [*template-declaration*](#nt:template-declaration "13.1Preamble[temp.pre]") is written
in terms of its template parameters[.](#9.sentence-1)
The optional [*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]") following a[*template-parameter-list*](#nt:template-parameter-list "13.1Preamble[temp.pre]") allows the specification of
constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations")) on template arguments ([[temp.arg]](temp.arg "13.4Template arguments"))[.](#9.sentence-2)
The [*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]") introduces the[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") that results from interpreting
the [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]") as a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")[.](#9.sentence-3)
The [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]") of a[*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3Context dependence"))[.](#9.sentence-4)
[*Note [7](#note-7)*:
The expression in a [*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]") uses a restricted grammar to avoid ambiguities[.](#9.sentence-5)
Parentheses can be used to specify arbitrary expressions
in a [*requires-clause*](#nt:requires-clause "13.1Preamble[temp.pre]")[.](#9.sentence-6)
[*Example [3](#example-3)*: template<int N> requires N == sizeof new unsigned shortint f(); // error: parentheses required around == expression — *end example*]
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L221)
A definition of
a function template,
member function of a class template,
variable template,
or static data member of a class template
shall be reachable from the end of every definition domain ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
in which it is implicitly instantiated ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")) unless the
corresponding specialization is explicitly instantiated ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))
in some translation unit; no diagnostic is required[.](#10.sentence-1)

1481
cppdraft/temp/res.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,343 @@
[temp.res.general]
# 13 Templates [[temp]](./#temp)
## 13.8 Name resolution [[temp.res]](temp.res#general)
### 13.8.1 General [temp.res.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4754)
A name that appears in a declaration D of a template T is looked up
from where it appears
in an unspecified declaration of T that either is D itself or is reachable from D and
from which no other declaration of T that contains the usage of the name is reachable[.](#1.sentence-1)
If the name is dependent (as specified in [[temp.dep]](temp.dep "13.8.3Dependent names")),
it is looked up for each specialization (after substitution)
because the lookup depends on a template parameter[.](#1.sentence-2)
[*Note [1](#note-1)*:
Some dependent names are also looked up during parsing to determine
that they are dependent or to interpret following < tokens[.](#1.sentence-3)
Uses of other names might be type-dependent or
value-dependent ([[temp.dep.expr]](temp.dep.expr "13.8.3.3Type-dependent expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4Value-dependent expressions"))[.](#1.sentence-4)
A [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") is never dependent in a specialization and
is therefore replaced during lookup for that specialization ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#1.sentence-5)
— *end note*]
[*Example [1](#example-1)*: struct A { operator int(); };template<class B, class T>struct D : B { T get() { return operator T(); } // [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") is dependent};int f(D<A, int> d) { return d.get(); } // OK, lookup finds A::operator int — *end example*]
[*Example [2](#example-2)*: void f(char);
template<class T> void g(T t) { f(1); // f(char) f(T(1)); // dependent f(t); // dependent dd++; // not dependent; error: declaration for dd not found}enum E { e };void f(E);
double dd;void h() { g(e); // will cause one call of f(char) followed by two calls of f(E) g('a'); // will cause three calls of f(char)} — *end example*]
[*Example [3](#example-3)*: struct A {struct B { /* ... */ }; int a; int Y;};
int a;
template<class T> struct Y : T {struct B { /* ... */ };
B b; // The B defined in Yvoid f(int i) { a = i; } // ::a Y* p; // Y<T>};
Y<A> ya;
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>[.](#1.sentence-6)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4828)
If the validity or meaning of the program would be changed by
considering a default argument or default template argument
introduced in a declaration that is reachable from
the point of instantiation of a specialization ([[temp.point]](temp.point "13.8.4.1Point of instantiation"))
but is not found by lookup for the specialization,
the program is ill-formed, no diagnostic required[.](#2.sentence-1)
[typename-specifier:](#nt:typename-specifier "13.8.1General[temp.res.general]")
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4842)
The component names of a [*typename-specifier*](#nt:typename-specifier "13.8.1General[temp.res.general]") are
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") (if any) and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") (if any)[.](#3.sentence-1)
A [*typename-specifier*](#nt:typename-specifier "13.8.1General[temp.res.general]") denotes the type or class template
denoted by the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers"))
formed by omitting the keyword typename[.](#3.sentence-2)
[*Note [2](#note-2)*:
The usual qualified name lookup ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup")) applies
even in the presence of typename[.](#3.sentence-3)
— *end note*]
[*Example [4](#example-4)*: struct A {struct X { }; int X;};struct B {struct X { };};template<class T> void f(T t) {typename T::X x;}void foo() { A a;
B b;
f(b); // OK, T::X refers to B::X f(a); // error: T::X refers to the data member A::X not the struct A::X} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4877)
A [*type-only context*](#def:context,type-only "13.8.1General[temp.res.general]") is defined as follows:
A qualified or unqualified name is said to be in
a type-only context if it is the terminal name of
- [(4.1)](#4.1)
a[*typename-specifier*](#nt:typename-specifier "13.8.1General[temp.res.general]"),[*type-requirement*](expr.prim.req.type#nt:type-requirement "7.5.8.3Type requirements[expr.prim.req.type]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]"),[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]"),[*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2The using enum declaration[enum.udecl]"),
or
- [(4.2)](#4.2)
a [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") of a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]"), or
- [(4.3)](#4.3)
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") of a
* [(4.3.1)](#4.3.1)
[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]"),
* [(4.3.2)](#4.3.2)
[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]"),
* [(4.3.3)](#4.3.3)
[*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]"),
* [(4.3.4)](#4.3.4)
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]"),
* [(4.3.5)](#4.3.5)
default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]"), or
* [(4.3.6)](#4.3.6)
[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast, or
- [(4.4)](#4.4)
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a
* [(4.4.1)](#4.4.1)
[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]") or [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") in namespace scope,
* [(4.4.2)](#4.4.2)
[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]"),
* [(4.4.3)](#4.4.3)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]"),[116](#footnote-116 "This includes friend function declarations.") unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument,
* [(4.4.4)](#4.4.4)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") of a function or function template declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is qualified,
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument,
* [(4.4.5)](#4.4.5)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") in a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") or [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1General[expr.prim.req.general]"),
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appears in a default argument, or
* [(4.4.6)](#4.4.6)
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") (which necessarily declares a constant template parameter)[.](#4.sentence-1)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") ([[basic.splice]](basic.splice "6.6Splice specifiers"))
is said to be in a type-only context
if a hypothetical qualified name appearing in the same position
would be in a type-only context[.](#4.sentence-2)
[*Example [5](#example-5)*: template<class T> T::R f(); // OK, return type of a function declaration at global scopetemplate<class T> void f(T::R); // ill-formed, no diagnostic required: attempt to declare// a void variable templateenum class Enum { A, B, C };template<class T> struct S {using Ptr = PtrTraits<T>::Ptr; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]")using Alias = [:^^int:]; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") T::R f(T::P p) { // OK, class scopereturn static_cast<T::R>(p); // OK, [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a static_cast}auto g() -> S<T*>::Ptr; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")auto h() -> [:^^S:]<T*>; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")using enum [:^^Enum:]; // OK, [*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2The using enum declaration[enum.udecl]")};template<typename T> void f() {void (*pf)(T::X); // variable pf of type void* initialized with T::Xvoid g(T::X); // error: T::X at block scope does not denote a type// (attempt to declare a void variable)} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4957)
A [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose terminal name is dependent and that is in a type-only context
is considered to denote a type[.](#5.sentence-1)
A name
that refers to a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") whose terminal name is dependent
is interpreted as a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") if the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") uses the keyword typename[.](#5.sentence-2)
[*Example [6](#example-6)*: template <class T> void f(int i) { T::x * i; // expression, not the declaration of a variable i}struct Foo {typedef int x;};
struct Bar {static int const x = 5;};
int main() { f<Bar>(1); // OK f<Foo>(1); // error: Foo::x is a type} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4986)
The validity of a templated entity may be checked prior to any instantiation[.](#6.sentence-1)
[*Note [3](#note-3)*:
Knowing which names are type names allows the syntax of every template
to be checked in this way[.](#6.sentence-2)
— *end note*]
The program is ill-formed, no diagnostic required, if
- [(6.1)](#6.1)
no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")s that fail ([[dcl.pre]](dcl.pre "9.1Preamble")),
can be generated for a templated entity
or a substatement of a constexpr if statement ([[stmt.if]](stmt.if "8.5.2The if statement"))
within a templated entity
and the innermost enclosing template is not instantiated, or
- [(6.2)](#6.2)
no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")s that fail,
can be generated for the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of an expansion statement and there is no instantiation of it, or
- [(6.3)](#6.3)
no valid specialization,
ignoring [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")s that fail,
can be generated for a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") and
the default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") is not used in any instantiation, or
- [(6.4)](#6.4)
no specialization of an alias template ([[temp.alias]](temp.alias "13.7.8Alias templates")) is valid and
no specialization of the alias template is named in the program, or
- [(6.5)](#6.5)
any [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") in the program, introduced or otherwise,
has (in its normal form) an atomic constraint A where
no satisfaction check of A could be well-formed and
no satisfaction check of A is performed, or
- [(6.6)](#6.6)
every valid specialization of a variadic template requires an empty template
parameter pack, or
- [(6.7)](#6.7)
a hypothetical instantiation of a templated entity
immediately following its definition
would be ill-formed
due to a construct
(other than a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]") that fails)
that does not depend on a template parameter, or
- [(6.8)](#6.8)
the interpretation of such a construct
in the hypothetical instantiation
is different from
the interpretation of the corresponding construct
in any actual instantiation of the templated entity[.](#6.sentence-3)
[*Note [4](#note-4)*:
This can happen in situations including the following:
- [(6.9)](#6.9)
a type used in a non-dependent name is incomplete at the point at which a
template is defined but is complete at the point at which an instantiation is
performed, or
- [(6.10)](#6.10)
lookup for a name in the template definition found a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]"),
but the lookup in the corresponding scope in the instantiation
does not find any declarations because the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") was a pack expansion and the corresponding pack is empty, or
- [(6.11)](#6.11)
an instantiation uses a default argument or default template argument
that had not been defined at the point at which the template was defined, or
- [(6.12)](#6.12)
[constant expression evaluation](expr.const "7.7Constant expressions[expr.const]") within the template
instantiation uses
* [(6.12.1)](#6.12.1)
the value of a const object of integral or unscoped enumeration type or
* [(6.12.2)](#6.12.2)
the value of a constexpr object or
* [(6.12.3)](#6.12.3)
the value of a reference or
* [(6.12.4)](#6.12.4)
the definition of a constexpr function,
and that entity was not defined when the template was defined, or
- [(6.13)](#6.13)
a class template specialization or variable template specialization that
is specified by a non-dependent [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is used by
the template, and either it is instantiated from a partial specialization that
was not defined when the template was defined or it names an explicit
specialization that was not declared when the template was defined[.](#6.sentence-4)
— *end note*]
[*Note [5](#note-5)*:
If a template is instantiated, errors will be diagnosed according
to the other rules in this document[.](#6.sentence-5)
Exactly when these errors are diagnosed is a quality of implementation issue[.](#6.sentence-6)
— *end note*]
[*Example [7](#example-7)*: int j;template<class T> class X {void f(T t, int i, char* p) { t = i; // diagnosed if X::f is instantiated, and the assignment to t is an error p = i; // may be diagnosed even if X::f is not instantiated p = j; // may be diagnosed even if X::f is not instantiated X<T>::g(t); // OK X<T>::h(); // may be diagnosed even if X::f is not instantiated}void g(T t) {+; // may be diagnosed even if X::g is not instantiated}};
template<class... T> struct A {void operator++(int, T... t); // error: too many parameters};template<class... T> union X : T... { }; // error: union with base classtemplate<class... T> struct A : T..., T... { }; // error: duplicate base class — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L5100)
[*Note [6](#note-6)*:
For purposes of name lookup, default arguments and[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")*s* of function templates and default
arguments and [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")*s* of
member functions of class templates are considered definitions ([[temp.decls]](temp.decls "13.7Template declarations"))[.](#7.sentence-1)
— *end note*]
[116)](#footnote-116)[116)](#footnoteref-116)
This includes friend function declarations[.](#footnote-116.sentence-1)

1136
cppdraft/temp/spec.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
[temp.spec.general]
# 13 Templates [[temp]](./#temp)
## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#general)
### 13.9.1 General [temp.spec.general]
[1](#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.1General[temp.spec.general]")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6352)
A function instantiated from a function template is called an instantiated
function[.](#2.sentence-1)
A class instantiated from a class template is called an instantiated class[.](#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[.](#2.sentence-3)
A member function instantiated from a member function template is called an
instantiated member function[.](#2.sentence-4)
A member class instantiated from a member class template is called an
instantiated member class[.](#2.sentence-5)
A variable instantiated from a variable template is called an
instantiated variable[.](#2.sentence-6)
A static data member instantiated from a static data member template
is called an instantiated static data member[.](#2.sentence-7)
[3](#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[.](#3.sentence-1)
An explicit specialization declaration is introduced bytemplate<>[.](#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.3Names of template specializations[temp.names]")[.](#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.3Names of template specializations[temp.names]")[.](#3.sentence-4)
[*Example [1](#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](#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.2Implicit instantiation")) for a given argument list or be explicitly
instantiated ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))[.](#4.sentence-1)
A [*specialization*](#def:specialization "13.9.1General[temp.spec.general]") is a class, variable, function, or class member that is either
instantiated ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")) from a templated entity or is an
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")) of a templated entity[.](#4.sentence-2)
[5](#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.3Names of template specializations[temp.names]")*s*,
- [(5.1)](#5.1)
an explicit instantiation definition shall appear at most once in a program,
- [(5.2)](#5.2)
an explicit specialization shall be defined at most once
in a program, as specified in [[basic.def.odr]](basic.def.odr "6.3One-definition rule"), and
- [(5.3)](#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[.](#5.sentence-1)
An implementation is not required to diagnose a violation of this rule
if neither declaration is reachable from the other[.](#5.sentence-2)
[6](#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.1General[class.derived.general]"), [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]"), [*enumerator-list*](dcl.enum#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]"),
or static data member or variable template initializer[.](#6.sentence-1)
[*Note [1](#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[.](#6.sentence-2)
— *end note*]
[7](#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[.](#7.sentence-1)
[*Example [2](#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*[.](#7.sentence-2)
— *end example*]
[8](#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.2Dependent types[temp.dep.type]") without using the syntactic form of
a function declarator, the program is ill-formed[.](#8.sentence-1)
[*Example [3](#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*]

View File

@@ -0,0 +1,345 @@
[temp.spec.partial]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial)
### 13.7.6 Partial specialization [temp.spec.partial]
#### [13.7.6.1](#general) General [[temp.spec.partial.general]](temp.spec.partial.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3655)
A partial specialization of a template provides an alternative definition
of the template that is used instead of the primary definition when the
arguments in a specialization match those given in the partial
specialization ([[temp.spec.partial.match]](#match "13.7.6.2Matching of partial specializations"))[.](#general-1.sentence-1)
A declaration of the primary template shall precede
any partial specialization of
that template[.](#general-1.sentence-2)
A partial specialization shall be reachable from any use of a template
specialization that would make use of the partial specialization as the result of
an implicit or explicit instantiation; no diagnostic is required[.](#general-1.sentence-3)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3668)
Two partial specialization declarations declare the same entity
if they are partial specializations of the same template and have equivalent[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* and template argument lists ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#general-2.sentence-1)
Each partial specialization is a distinct template[.](#general-2.sentence-2)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3674)
[*Example [1](#general-example-1)*: template<class T1, class T2, int I> class A { };template<class T, int I> class A<T, T*, I> { };template<class T1, class T2, int I> class A<T1*, T2, I> { };template<class T> class A<int, T*, 5> { };template<class T1, class T2, int I> class A<T1, T2*, I> { };
The first declaration declares the primary (unspecialized) class template[.](#general-3.sentence-1)
The second and subsequent declarations declare partial specializations of
the primary template[.](#general-3.sentence-2)
— *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3689)
A partial specialization may be constrained ([[temp.constr]](temp.constr "13.5Template constraints"))[.](#general-4.sentence-1)
[*Example [2](#general-example-2)*: template<typename T> concept C = true;
template<typename T> struct X { };template<typename T> struct X<T*> { }; // #1template<C T> struct X<T> { }; // #2
Both partial specializations are more specialized than the primary template[.](#general-4.sentence-2)
#1 is more specialized because the deduction of its template arguments
from the template argument list of the class template specialization succeeds,
while the reverse does not[.](#general-4.sentence-3)
#2 is more specialized because the template arguments are equivalent,
but the partial specialization is more constrained ([[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints"))[.](#general-4.sentence-4)
— *end example*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3707)
The template argument list of a partial specialization is
the [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") following the name of the template[.](#general-5.sentence-1)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3711)
A partial specialization may be declared in any
scope in which the corresponding primary template
may be defined ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[class.mem]](class.mem "11.4Class members"), [[temp.mem]](temp.mem "13.7.3Member templates"))[.](#general-6.sentence-1)
[*Example [3](#general-example-3)*: template<class T> struct A {struct C {template<class T2> struct B { }; template<class T2> struct B<T2**> { }; // partial specialization #1};};
// partial specialization of A<T>::C::B<T2>template<class T> template<class T2>struct A<T>::C::B<T2*> { }; // #2 A<short>::C::B<int*> absip; // uses partial specialization #2 — *end example*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3732)
Partial specialization declarations do not introduce a name[.](#general-7.sentence-1)
Instead, when the primary template name is used, any reachable partial
specializations of the primary template are also considered[.](#general-7.sentence-2)
[*Note [1](#general-note-1)*:
One consequence is
that a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") which refers to a class template does not restrict the set of partial specializations
that are found through the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")[.](#general-7.sentence-3)
— *end note*]
[*Example [4](#general-example-4)*: namespace N {template<class T1, class T2> class A { }; // primary template}using N::A; // refers to the primary templatenamespace N {template<class T> class A<T, T*> { }; // partial specialization} A<int,int*> a; // uses the partial specialization, which is found through the using-declaration// which refers to the primary template — *end example*]
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3759)
A constant template argument is non-specialized if it is the name of a constant
template parameter[.](#general-8.sentence-1)
All other constant template arguments are specialized[.](#general-8.sentence-2)
[9](#general-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3764)
Within the argument list of a partial specialization,
the following restrictions apply:
- [(9.1)](#general-9.1)
The type of a template parameter corresponding to a specialized constant template
argument shall not be dependent on a parameter of the partial specialization[.](#general-9.1.sentence-1)
[*Example [5](#general-example-5)*: template <class T, T t> struct C {};template <class T> struct C<T, 1>; // errortemplate< int X, int (*array_ptr)[X] > class A {};int array[5];template< int X > class A<X,&array> { }; // error — *end example*]
- [(9.2)](#general-9.2)
The partial specialization shall be more specialized than the primary
template ([[temp.spec.partial.order]](#order "13.7.6.3Partial ordering of partial specializations"))[.](#general-9.2.sentence-1)
- [(9.3)](#general-9.3)
The template parameter list of a partial specialization shall not contain default
template argument values[.](#general-9.3.sentence-1)[114](#footnote-114 "There is no context in which they would be used.")
- [(9.4)](#general-9.4)
An argument shall not contain an unexpanded pack[.](#general-9.4.sentence-1)
If
an argument is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), it shall be
the last argument in the template argument list[.](#general-9.4.sentence-2)
[10](#general-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3797)
The usual access checking rules do not apply to non-dependent names
used to specify template arguments of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") of the partial specialization[.](#general-10.sentence-1)
[*Note [2](#general-note-2)*:
The template arguments can be private types or
objects that would normally not be accessible[.](#general-10.sentence-2)
Dependent names cannot be checked when declaring the partial specialization,
but will be checked when substituting into the partial specialization[.](#general-10.sentence-3)
— *end note*]
[114)](#footnote-114)[114)](#footnoteref-114)
There is no context in which they would be used[.](#footnote-114.sentence-1)
#### [13.7.6.2](#match) Matching of partial specializations [[temp.spec.partial.match]](temp.spec.partial.match)
[1](#match-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3810)
When a template is used in a context that requires an instantiation of
the template,
it is necessary to determine whether the instantiation is to be generated
using the primary template or one of the partial specializations[.](#match-1.sentence-1)
This is done by matching the template arguments of the template
specialization with the template argument lists of the partial
specializations[.](#match-1.sentence-2)
- [(1.1)](#match-1.1)
If exactly one matching partial specialization is found, the instantiation is
generated from that partial specialization[.](#match-1.1.sentence-1)
- [(1.2)](#match-1.2)
If more than one matching partial specialization is found,
the partial order rules ([[temp.spec.partial.order]](#order "13.7.6.3Partial ordering of partial specializations")) are used to determine
whether one of the partial specializations is more specialized than the
others[.](#match-1.2.sentence-1)
If such a partial specialization exists,
the instantiation is generated from that partial specialization;
otherwise, the use of the template is ambiguous and the program is ill-formed[.](#match-1.2.sentence-2)
- [(1.3)](#match-1.3)
If no matches are found, the instantiation is generated from the
primary template[.](#match-1.3.sentence-1)
[2](#match-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3836)
A partial specialization matches a given actual template argument
list if the template arguments of the partial specialization can be[deduced](temp.deduct "13.10.3Template argument deduction[temp.deduct]") from the actual template argument list,
and the deduced template arguments satisfy the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") of the partial specialization, if any[.](#match-2.sentence-1)
[*Example [1](#match-example-1)*: template<class T1, class T2, int I> class A { }; // #1template<class T, int I> class A<T, T*, I> { }; // #2template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3template<class T> class A<int, T*, 5> { }; // #4template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 — *end example*]
[*Example [2](#match-example-2)*: template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> struct S { }; // #1template<C T> struct S<T> { }; // #2struct Arg { void f(); };
S<int> s1; // uses #1; the constraints of #2 are not satisfied S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized — *end example*]
[3](#match-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3871)
If the template arguments of a partial specialization cannot be deduced
because of the structure of its [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") and the [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"),
the program is ill-formed[.](#match-3.sentence-1)
[*Example [3](#match-example-3)*: template <int I, int J> struct A {};template <int I> struct A<I+5, I*2> {}; // errortemplate <int I> struct A<I, I> {}; // OKtemplate <int I, int J, int K> struct B {};template <int I> struct B<I, I*2, 2> {}; // OK — *end example*]
[4](#match-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3888)
In a name that refers to a specialization of a class or variable template
(e.g., A<int, int, 1>),
the argument list shall match the template parameter list of the primary
template[.](#match-4.sentence-1)
The template arguments of a partial specialization are deduced from the arguments
of the primary template[.](#match-4.sentence-2)
#### [13.7.6.3](#order) Partial ordering of partial specializations [[temp.spec.partial.order]](temp.spec.partial.order)
[1](#order-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3898)
For two partial specializations,
the first is [*more specialized*](temp.deduct.partial#def:more_specialized "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]") than the second if, given the following
rewrite to two function templates, the first function template is more
specialized than the second according to the [ordering rules for function
templates](temp.func.order "13.7.7.3Partial ordering of function templates[temp.func.order]"):
- [(1.1)](#order-1.1)
Each of the two
function templates has the same template parameters
and [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") as the corresponding partial specialization[.](#order-1.1.sentence-1)
- [(1.2)](#order-1.2)
Each function template
has a single function parameter
whose type is a class template specialization where the template arguments
are the corresponding template parameters from the function template
for each template argument
in the [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") of the partial specialization[.](#order-1.2.sentence-1)
[2](#order-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3922)
[*Example [1](#order-example-1)*: template<int I, int J, class T> class X { };template<int I, int J> class X<I, J, int> { }; // #1template<int I> class X<I, I, int> { }; // #2template<int I0, int J0> void f(X<I0, J0, int>); // Atemplate<int I0> void f(X<I0, I0, int>); // Btemplate <auto v> class Y { };template <auto* p> class Y<p> { }; // #3template <auto** pp> class Y<pp> { }; // #4template <auto* p0> void g(Y<p0>); // Ctemplate <auto** pp0> void g(Y<pp0>); // D
According to the ordering rules for function templates,
the function template*B* is more specialized than the function template*A* and
the function template*D* is more specialized than the function template*C*[.](#order-2.sentence-1)
Therefore, the partial specialization #2
is more specialized than the partial specialization #1
and the partial specialization #4
is more specialized than the partial specialization #3[.](#order-2.sentence-2)
— *end example*]
[*Example [2](#order-example-2)*: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.f(); };
template<typename T> class S { };template<C T> class S<T> { }; // #1template<D T> class S<T> { }; // #2template<C T> void f(S<T>); // Atemplate<D T> void f(S<T>); // B
The partial specialization #2 is more specialized than #1
because B is more specialized than A[.](#order-2.sentence-3)
— *end example*]
#### [13.7.6.4](#member) Members of class template partial specializations [[temp.spec.partial.member]](temp.spec.partial.member)
[1](#member-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3973)
The members of the class template partial specialization are
unrelated to the members of the primary template[.](#member-1.sentence-1)
Class template partial specialization members that are used in a way that
requires a definition shall be defined; the definitions of members of the
primary template are never used as definitions for members of a class
template partial specialization[.](#member-1.sentence-2)
An explicit specialization of a member of a class template partial
specialization is declared in the same way as an explicit specialization of
a member of the primary template[.](#member-1.sentence-3)
[*Example [1](#member-example-1)*: // primary class templatetemplate<class T, int I> struct A {void f();};
// member of primary class templatetemplate<class T, int I> void A<T,I>::f() { }// class template partial specializationtemplate<class T> struct A<T,2> {void f(); void g(); void h();};
// member of class template partial specializationtemplate<class T> void A<T,2>::g() { }// explicit specializationtemplate<> void A<char,2>::h() { }int main() { A<char,0> a0;
A<char,2> a2;
a0.f(); // OK, uses definition of primary template's member a2.g(); // OK, uses definition of partial specialization's member a2.h(); // OK, uses definition of explicit specialization's member a2.f(); // error: no definition of f for A<T,2>; the primary template is not used here} — *end example*]
[2](#member-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4017)
If a member template of a class template is partially specialized,
the member template partial specializations are member templates of
the enclosing class template;
if the enclosing class template is instantiated ([[temp.inst]](temp.inst "13.9.2Implicit instantiation"), [[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")),
a declaration for every member template partial specialization is also
instantiated as part of creating the members of the class template
specialization[.](#member-2.sentence-1)
If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template,
the partial specializations of the member template are ignored for this
specialization of the enclosing class template[.](#member-2.sentence-2)
If a partial specialization of the member template is explicitly specialized
for a given (implicit) specialization of the enclosing class template,
the primary member template and its other partial specializations are
still considered for this specialization of the enclosing class template[.](#member-2.sentence-3)
[*Example [2](#member-example-2)*: template<class T> struct A {template<class T2> struct B {}; // #1template<class T2> struct B<T2*> {}; // #2};
template<> template<class T2> struct A<short>::B {}; // #3 A<char>::B<int*> abcip; // uses #2 A<short>::B<int*> absip; // uses #3 A<char>::B<int> abci; // uses #1 — *end example*]

View File

@@ -0,0 +1,167 @@
[temp.spec.partial.general]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial.general)
### 13.7.6 Partial specialization [[temp.spec.partial]](temp.spec.partial#general)
#### 13.7.6.1 General [temp.spec.partial.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3655)
A partial specialization of a template provides an alternative definition
of the template that is used instead of the primary definition when the
arguments in a specialization match those given in the partial
specialization ([[temp.spec.partial.match]](temp.spec.partial.match "13.7.6.2Matching of partial specializations"))[.](#1.sentence-1)
A declaration of the primary template shall precede
any partial specialization of
that template[.](#1.sentence-2)
A partial specialization shall be reachable from any use of a template
specialization that would make use of the partial specialization as the result of
an implicit or explicit instantiation; no diagnostic is required[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3668)
Two partial specialization declarations declare the same entity
if they are partial specializations of the same template and have equivalent[*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")*s* and template argument lists ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#2.sentence-1)
Each partial specialization is a distinct template[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3674)
[*Example [1](#example-1)*: template<class T1, class T2, int I> class A { };template<class T, int I> class A<T, T*, I> { };template<class T1, class T2, int I> class A<T1*, T2, I> { };template<class T> class A<int, T*, 5> { };template<class T1, class T2, int I> class A<T1, T2*, I> { };
The first declaration declares the primary (unspecialized) class template[.](#3.sentence-1)
The second and subsequent declarations declare partial specializations of
the primary template[.](#3.sentence-2)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3689)
A partial specialization may be constrained ([[temp.constr]](temp.constr "13.5Template constraints"))[.](#4.sentence-1)
[*Example [2](#example-2)*: template<typename T> concept C = true;
template<typename T> struct X { };template<typename T> struct X<T*> { }; // #1template<C T> struct X<T> { }; // #2
Both partial specializations are more specialized than the primary template[.](#4.sentence-2)
#1 is more specialized because the deduction of its template arguments
from the template argument list of the class template specialization succeeds,
while the reverse does not[.](#4.sentence-3)
#2 is more specialized because the template arguments are equivalent,
but the partial specialization is more constrained ([[temp.constr.order]](temp.constr.order "13.5.5Partial ordering by constraints"))[.](#4.sentence-4)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3707)
The template argument list of a partial specialization is
the [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") following the name of the template[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3711)
A partial specialization may be declared in any
scope in which the corresponding primary template
may be defined ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[class.mem]](class.mem "11.4Class members"), [[temp.mem]](temp.mem "13.7.3Member templates"))[.](#6.sentence-1)
[*Example [3](#example-3)*: template<class T> struct A {struct C {template<class T2> struct B { }; template<class T2> struct B<T2**> { }; // partial specialization #1};};
// partial specialization of A<T>::C::B<T2>template<class T> template<class T2>struct A<T>::C::B<T2*> { }; // #2 A<short>::C::B<int*> absip; // uses partial specialization #2 — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3732)
Partial specialization declarations do not introduce a name[.](#7.sentence-1)
Instead, when the primary template name is used, any reachable partial
specializations of the primary template are also considered[.](#7.sentence-2)
[*Note [1](#note-1)*:
One consequence is
that a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") which refers to a class template does not restrict the set of partial specializations
that are found through the [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")[.](#7.sentence-3)
— *end note*]
[*Example [4](#example-4)*: namespace N {template<class T1, class T2> class A { }; // primary template}using N::A; // refers to the primary templatenamespace N {template<class T> class A<T, T*> { }; // partial specialization} A<int,int*> a; // uses the partial specialization, which is found through the using-declaration// which refers to the primary template — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3759)
A constant template argument is non-specialized if it is the name of a constant
template parameter[.](#8.sentence-1)
All other constant template arguments are specialized[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3764)
Within the argument list of a partial specialization,
the following restrictions apply:
- [(9.1)](#9.1)
The type of a template parameter corresponding to a specialized constant template
argument shall not be dependent on a parameter of the partial specialization[.](#9.1.sentence-1)
[*Example [5](#example-5)*: template <class T, T t> struct C {};template <class T> struct C<T, 1>; // errortemplate< int X, int (*array_ptr)[X] > class A {};int array[5];template< int X > class A<X,&array> { }; // error — *end example*]
- [(9.2)](#9.2)
The partial specialization shall be more specialized than the primary
template ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3Partial ordering of partial specializations"))[.](#9.2.sentence-1)
- [(9.3)](#9.3)
The template parameter list of a partial specialization shall not contain default
template argument values[.](#9.3.sentence-1)[114](#footnote-114 "There is no context in which they would be used.")
- [(9.4)](#9.4)
An argument shall not contain an unexpanded pack[.](#9.4.sentence-1)
If
an argument is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), it shall be
the last argument in the template argument list[.](#9.4.sentence-2)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3797)
The usual access checking rules do not apply to non-dependent names
used to specify template arguments of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") of the partial specialization[.](#10.sentence-1)
[*Note [2](#note-2)*:
The template arguments can be private types or
objects that would normally not be accessible[.](#10.sentence-2)
Dependent names cannot be checked when declaring the partial specialization,
but will be checked when substituting into the partial specialization[.](#10.sentence-3)
— *end note*]
[114)](#footnote-114)[114)](#footnoteref-114)
There is no context in which they would be used[.](#footnote-114.sentence-1)

View File

@@ -0,0 +1,80 @@
[temp.spec.partial.match]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial.match)
### 13.7.6 Partial specialization [[temp.spec.partial]](temp.spec.partial#match)
#### 13.7.6.2 Matching of partial specializations [temp.spec.partial.match]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3810)
When a template is used in a context that requires an instantiation of
the template,
it is necessary to determine whether the instantiation is to be generated
using the primary template or one of the partial specializations[.](#1.sentence-1)
This is done by matching the template arguments of the template
specialization with the template argument lists of the partial
specializations[.](#1.sentence-2)
- [(1.1)](#1.1)
If exactly one matching partial specialization is found, the instantiation is
generated from that partial specialization[.](#1.1.sentence-1)
- [(1.2)](#1.2)
If more than one matching partial specialization is found,
the partial order rules ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3Partial ordering of partial specializations")) are used to determine
whether one of the partial specializations is more specialized than the
others[.](#1.2.sentence-1)
If such a partial specialization exists,
the instantiation is generated from that partial specialization;
otherwise, the use of the template is ambiguous and the program is ill-formed[.](#1.2.sentence-2)
- [(1.3)](#1.3)
If no matches are found, the instantiation is generated from the
primary template[.](#1.3.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3836)
A partial specialization matches a given actual template argument
list if the template arguments of the partial specialization can be[deduced](temp.deduct "13.10.3Template argument deduction[temp.deduct]") from the actual template argument list,
and the deduced template arguments satisfy the [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") of the partial specialization, if any[.](#2.sentence-1)
[*Example [1](#example-1)*: template<class T1, class T2, int I> class A { }; // #1template<class T, int I> class A<T, T*, I> { }; // #2template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3template<class T> class A<int, T*, 5> { }; // #4template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5 A<int, int, 1> a1; // uses #1 A<int, int*, 1> a2; // uses #2, T is int, I is 1 A<int, char*, 5> a3; // uses #4, T is char A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1 A<int*, int*, 2> a5; // ambiguous: matches #3 and #5 — *end example*]
[*Example [2](#example-2)*: template<typename T> concept C = requires (T t) { t.f(); };
template<typename T> struct S { }; // #1template<C T> struct S<T> { }; // #2struct Arg { void f(); };
S<int> s1; // uses #1; the constraints of #2 are not satisfied S<Arg> s2; // uses #2; both constraints are satisfied but #2 is more specialized — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3871)
If the template arguments of a partial specialization cannot be deduced
because of the structure of its [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") and the [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"),
the program is ill-formed[.](#3.sentence-1)
[*Example [3](#example-3)*: template <int I, int J> struct A {};template <int I> struct A<I+5, I*2> {}; // errortemplate <int I> struct A<I, I> {}; // OKtemplate <int I, int J, int K> struct B {};template <int I> struct B<I, I*2, 2> {}; // OK — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3888)
In a name that refers to a specialization of a class or variable template
(e.g., A<int, int, 1>),
the argument list shall match the template parameter list of the primary
template[.](#4.sentence-1)
The template arguments of a partial specialization are deduced from the arguments
of the primary template[.](#4.sentence-2)

View File

@@ -0,0 +1,59 @@
[temp.spec.partial.member]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial.member)
### 13.7.6 Partial specialization [[temp.spec.partial]](temp.spec.partial#member)
#### 13.7.6.4 Members of class template partial specializations [temp.spec.partial.member]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3973)
The members of the class template partial specialization are
unrelated to the members of the primary template[.](#1.sentence-1)
Class template partial specialization members that are used in a way that
requires a definition shall be defined; the definitions of members of the
primary template are never used as definitions for members of a class
template partial specialization[.](#1.sentence-2)
An explicit specialization of a member of a class template partial
specialization is declared in the same way as an explicit specialization of
a member of the primary template[.](#1.sentence-3)
[*Example [1](#example-1)*: // primary class templatetemplate<class T, int I> struct A {void f();};
// member of primary class templatetemplate<class T, int I> void A<T,I>::f() { }// class template partial specializationtemplate<class T> struct A<T,2> {void f(); void g(); void h();};
// member of class template partial specializationtemplate<class T> void A<T,2>::g() { }// explicit specializationtemplate<> void A<char,2>::h() { }int main() { A<char,0> a0;
A<char,2> a2;
a0.f(); // OK, uses definition of primary template's member a2.g(); // OK, uses definition of partial specialization's member a2.h(); // OK, uses definition of explicit specialization's member a2.f(); // error: no definition of f for A<T,2>; the primary template is not used here} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4017)
If a member template of a class template is partially specialized,
the member template partial specializations are member templates of
the enclosing class template;
if the enclosing class template is instantiated ([[temp.inst]](temp.inst "13.9.2Implicit instantiation"), [[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")),
a declaration for every member template partial specialization is also
instantiated as part of creating the members of the class template
specialization[.](#2.sentence-1)
If the primary member template is explicitly specialized for a given
(implicit) specialization of the enclosing class template,
the partial specializations of the member template are ignored for this
specialization of the enclosing class template[.](#2.sentence-2)
If a partial specialization of the member template is explicitly specialized
for a given (implicit) specialization of the enclosing class template,
the primary member template and its other partial specializations are
still considered for this specialization of the enclosing class template[.](#2.sentence-3)
[*Example [2](#example-2)*: template<class T> struct A {template<class T2> struct B {}; // #1template<class T2> struct B<T2*> {}; // #2};
template<> template<class T2> struct A<short>::B {}; // #3 A<char>::B<int*> abcip; // uses #2 A<short>::B<int*> absip; // uses #3 A<char>::B<int> abci; // uses #1 — *end example*]

View File

@@ -0,0 +1,60 @@
[temp.spec.partial.order]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.spec.partial.order)
### 13.7.6 Partial specialization [[temp.spec.partial]](temp.spec.partial#order)
#### 13.7.6.3 Partial ordering of partial specializations [temp.spec.partial.order]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3898)
For two partial specializations,
the first is [*more specialized*](temp.deduct.partial#def:more_specialized "13.10.3.5Deducing template arguments during partial ordering[temp.deduct.partial]") than the second if, given the following
rewrite to two function templates, the first function template is more
specialized than the second according to the [ordering rules for function
templates](temp.func.order "13.7.7.3Partial ordering of function templates[temp.func.order]"):
- [(1.1)](#1.1)
Each of the two
function templates has the same template parameters
and [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3Constrained declarations[temp.constr.decl]") as the corresponding partial specialization[.](#1.1.sentence-1)
- [(1.2)](#1.2)
Each function template
has a single function parameter
whose type is a class template specialization where the template arguments
are the corresponding template parameters from the function template
for each template argument
in the [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") of the partial specialization[.](#1.2.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3922)
[*Example [1](#example-1)*: template<int I, int J, class T> class X { };template<int I, int J> class X<I, J, int> { }; // #1template<int I> class X<I, I, int> { }; // #2template<int I0, int J0> void f(X<I0, J0, int>); // Atemplate<int I0> void f(X<I0, I0, int>); // Btemplate <auto v> class Y { };template <auto* p> class Y<p> { }; // #3template <auto** pp> class Y<pp> { }; // #4template <auto* p0> void g(Y<p0>); // Ctemplate <auto** pp0> void g(Y<pp0>); // D
According to the ordering rules for function templates,
the function template*B* is more specialized than the function template*A* and
the function template*D* is more specialized than the function template*C*[.](#2.sentence-1)
Therefore, the partial specialization #2
is more specialized than the partial specialization #1
and the partial specialization #4
is more specialized than the partial specialization #3[.](#2.sentence-2)
— *end example*]
[*Example [2](#example-2)*: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.f(); };
template<typename T> class S { };template<C T> class S<T> { }; // #1template<D T> class S<T> { }; // #2template<C T> void f(S<T>); // Atemplate<D T> void f(S<T>); // B
The partial specialization #2 is more specialized than #1
because B is more specialized than A[.](#2.sentence-3)
— *end example*]

32
cppdraft/temp/static.md Normal file
View File

@@ -0,0 +1,32 @@
[temp.static]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.static)
### 13.7.2 Class templates [[temp.class]](temp.class#temp.static)
#### 13.7.2.5 Static data members of class templates [temp.static]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2899)
A definition for a static data member or static data member template may be
provided in a namespace scope enclosing the definition of the static member's
class template[.](#1.sentence-1)
[*Example [1](#example-1)*: template<class T> class X {static T s;};template<class T> T X<T>::s = 0;
struct limits {template<class T>static const T min; // declaration};
template<class T>const T limits::min = { }; // definition — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2921)
An explicit specialization of a static data member declared as an array of unknown
bound can have a different bound from its definition, if any[.](#2.sentence-1)
[*Example [2](#example-2)*: template <class T> struct A {static int i[];};template <class T> int A<T>::i[4]; // 4 elementstemplate <> int A<int>::i[] = { 1 }; // OK, 1 element — *end example*]

156
cppdraft/temp/type.md Normal file
View File

@@ -0,0 +1,156 @@
[temp.type]
# 13 Templates [[temp]](./#temp)
## 13.6 Type equivalence [temp.type]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2445)
Two [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")*s* are the same if
- [(1.1)](#1.1)
their [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")*s*,[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1General[over.oper.general]")*s*, or[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6User-defined literals[over.literal]")*s* refer to the same template, and
- [(1.2)](#1.2)
their corresponding type [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* are the same type, and
- [(1.3)](#1.3)
the template parameter values determined by
their corresponding constant template arguments ([[temp.arg.nontype]](temp.arg.nontype "13.4.3Constant template arguments"))
are template-argument-equivalent (see below), and
- [(1.4)](#1.4)
their corresponding template [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")*s* refer to the same template[.](#1.sentence-1)
Two [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")*s* that are the same
refer to the same class, function, or variable[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2471)
Two values are [*template-argument-equivalent*](#def:template-argument-equivalent "13.6Type equivalence[temp.type]") if
they are of the same type and
- [(2.1)](#2.1)
they are of integral type and their values are the same, or
- [(2.2)](#2.2)
they are of floating-point type and their values are identical, or
- [(2.3)](#2.3)
they are of type std::nullptr_t, or
- [(2.4)](#2.4)
they are of type std::meta::info and
their values compare equal ([[expr.eq]](expr.eq "7.6.10Equality operators")), or
- [(2.5)](#2.5)
they are of enumeration type and their values are the same,[112](#footnote-112 "The identity of enumerators is not preserved.") or
- [(2.6)](#2.6)
they are of pointer type and they have the same pointer value, or
- [(2.7)](#2.7)
they are of pointer-to-member type and they refer to the same class member
or are both the null member pointer value, or
- [(2.8)](#2.8)
they are of reference type and they refer to the same object or function, or
- [(2.9)](#2.9)
they are of array type and their corresponding elements are template-argument-equivalent,[113](#footnote-113 "An array as a template-parameter decays to a pointer.") or
- [(2.10)](#2.10)
they are of union type and either
they both have no active member or
they have the same active member and their active members are template-argument-equivalent, or
- [(2.11)](#2.11)
they are of a closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types")), or
- [(2.12)](#2.12)
they are of class type and
their corresponding direct subobjects and reference members are template-argument-equivalent[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2525)
[*Example [1](#example-1)*:
template<class E, int size> class buffer { /* ... */ };
buffer<char,2*512> x;
buffer<char,1024> y; declaresx andy to be of the same type, andtemplate<class T, void(*err_fct)()> class list { /* ... */ };
list<int,&error_handler1> x1;
list<int,&error_handler2> x2;
list<int,&error_handler2> x3;
list<char,&error_handler2> x4; declaresx2 andx3 to be of the same type[.](#3.sentence-1)
Their type differs from the types ofx1 andx4[.](#3.sentence-2)
template<class T> struct X { };template<class> struct Y { };template<class T> using Z = Y<T>;
X<Y<int> > y;
X<Z<int> > z; declares y and z to be of the same type[.](#3.sentence-3)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2564)
If an expression e is [type-dependent](temp.dep.expr "13.8.3.3Type-dependent expressions[temp.dep.expr]"),decltype(e) denotes a unique dependent type[.](#4.sentence-1)
Two such [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]")*s* refer to the same type only if their [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")*s* are
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#4.sentence-2)
[*Note [1](#note-1)*:
However, such a type might be aliased,
e.g., by a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")[.](#4.sentence-3)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2575)
For a type template parameter pack T,T...[[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")] denotes
a unique dependent type[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2580)
If the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") of a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") is value-dependent,
two such [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]")*s* refer to the same type
only if their [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")*s* are equivalent ([[temp.over.link]](temp.over.link "13.7.7.2Function template overloading"))[.](#6.sentence-1)
Otherwise, two such [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]")*s* refer to the same type
only if their indexes have the same value[.](#6.sentence-2)
[112)](#footnote-112)[112)](#footnoteref-112)
The identity of enumerators is not preserved[.](#footnote-112.sentence-1)
[113)](#footnote-113)[113)](#footnoteref-113)
An array as a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") decays to a pointer[.](#footnote-113.sentence-1)

370
cppdraft/temp/variadic.md Normal file
View File

@@ -0,0 +1,370 @@
[temp.variadic]
# 13 Templates [[temp]](./#temp)
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.variadic)
### 13.7.4 Variadic templates [temp.variadic]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3082)
A [*template parameter pack*](#def:template_parameter_pack "13.7.4Variadic templates[temp.variadic]") is a template parameter
that accepts zero or more template arguments[.](#1.sentence-1)
[*Example [1](#example-1)*: template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Types contains one argument: int Tuple<int, float> t2; // Types contains two arguments: int and float Tuple<0> error; // error: 0 is not a type — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3096)
A [*function parameter pack*](#def:function_parameter_pack "13.7.4Variadic templates[temp.variadic]") is a function parameter
that accepts zero or more function arguments[.](#2.sentence-1)
[*Example [2](#example-2)*: template<class ... Types> void f(Types ... args);
f(); // args contains no arguments f(1); // args contains one argument: int f(2, 1.0); // args contains two arguments: int and double — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3109)
An [](#def:init-capture_pack "13.7.4Variadic templates[temp.variadic]")*[*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack* is a lambda capture that introduces an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") for each of the elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#3.sentence-1)
[*Example [3](#example-3)*: template <typename... Args>void foo(Args... args) {[...xs=args]{ bar(xs...); // xs is an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack};} foo(); // xs contains zero [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]")*s* foo(1); // xs contains one [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3127)
A [*structured binding pack*](#def:structured_binding_pack "13.7.4Variadic templates[temp.variadic]") is an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1Preamble[dcl.pre]") that introduces zero or more structured bindings ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#4.sentence-1)
[*Example [4](#example-4)*: auto foo() -> int(&)[2];
template <class T>void g() {auto [...a] = foo(); // a is a structured binding pack containing two elementsauto [b, c, ...d] = foo(); // d is a structured binding pack containing zero elements} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3142)
A [*pack*](#def:pack "13.7.4Variadic templates[temp.variadic]") is
a template parameter pack,
a function parameter pack,
an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack, or
a structured binding pack[.](#5.sentence-1)
The number of elements of a template parameter pack
or a function parameter pack
is the number of arguments provided for the parameter pack[.](#5.sentence-2)
The number of elements of an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack
is the number of elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3154)
A [*pack expansion*](#def:pack_expansion "13.7.4Variadic templates[temp.variadic]") consists of a [*pattern*](#def:pack_expansion,pattern "13.7.4Variadic templates[temp.variadic]") and an ellipsis, the instantiation of which
produces zero or more instantiations of the pattern in a list (described below)[.](#6.sentence-1)
The form of the pattern
depends on the context in which the expansion occurs[.](#6.sentence-2)
Pack
expansions can occur in the following contexts:
- [(6.1)](#6.1)
In a function parameter pack ([[dcl.fct]](dcl.fct "9.3.4.6Functions")); the pattern is the[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") without the ellipsis[.](#6.1.sentence-1)
- [(6.2)](#6.2)
In a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10The using declaration"));
the pattern is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]")[.](#6.2.sentence-1)
- [(6.3)](#6.3)
In a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]") ([[class.mem.general]](class.mem.general "11.4.1General"));
the pattern is a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]")[.](#6.3.sentence-1)
- [(6.4)](#6.4)
In a template parameter pack that is a pack expansion ([[temp.param]](temp.param "13.2Template parameters")):
* [(6.4.1)](#6.4.1)
if the template parameter pack is a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]");
the pattern is the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") without the ellipsis;
* [(6.4.2)](#6.4.2)
if the template parameter pack is a [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]");
the pattern is the corresponding [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") without the ellipsis;
* [(6.4.3)](#6.4.3)
if the template parameter pack is a template template parameter;
the pattern is the corresponding[*type-tt-parameter*](temp.param#nt:type-tt-parameter "13.2Template parameters[temp.param]"),[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2Template parameters[temp.param]"), or[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2Template parameters[temp.param]") without the ellipsis[.](#6.4.sentence-1)
- [(6.5)](#6.5)
In an [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") ([[dcl.init]](dcl.init "9.5Initializers"));
the pattern is an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#6.5.sentence-1)
- [(6.6)](#6.6)
In a [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") ([[class.derived]](class.derived "11.7Derived classes"));
the pattern is a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")[.](#6.6.sentence-1)
- [(6.7)](#6.7)
In a [*mem-initializer-list*](class.base.init#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")) for a[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") whose [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") denotes a
base class; the pattern is the [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")[.](#6.7.sentence-1)
- [(6.8)](#6.8)
In a [*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]") ([[temp.arg]](temp.arg "13.4Template arguments"));
the pattern is a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]")[.](#6.8.sentence-1)
- [(6.9)](#6.9)
In an [*attribute-list*](dcl.attr.grammar#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1Attribute syntax and semantics"));
the pattern is an [*attribute*](dcl.attr.grammar#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#6.9.sentence-1)
- [(6.10)](#6.10)
In an [*annotation-list*](dcl.attr.grammar#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1Attribute syntax and semantics"));
the pattern is an [*annotation*](dcl.attr.grammar#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#6.10.sentence-1)
- [(6.11)](#6.11)
In an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2Alignment specifier")); the pattern is
the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") without the ellipsis[.](#6.11.sentence-1)
- [(6.12)](#6.12)
In a [*capture-list*](expr.prim.lambda.capture#nt:capture-list "7.5.6.3Captures[expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures")); the pattern is
the [*capture*](expr.prim.lambda.capture#nt:capture "7.5.6.3Captures[expr.prim.lambda.capture]") without the ellipsis[.](#6.12.sentence-1)
- [(6.13)](#6.13)
In a [sizeof... expression](expr.sizeof "7.6.2.5Sizeof[expr.sizeof]"); the pattern is an[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")[.](#6.13.sentence-1)
- [(6.14)](#6.14)
In a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]");
the pattern is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")[.](#6.14.sentence-1)
- [(6.15)](#6.15)
In a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]");
the pattern is a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")[.](#6.15.sentence-1)
- [(6.16)](#6.16)
In a [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7Fold expressions"));
the pattern is the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") that contains an unexpanded pack[.](#6.16.sentence-1)
- [(6.17)](#6.17)
In a fold expanded constraint ([[temp.constr.fold]](temp.constr.fold "13.5.2.5Fold expanded constraint"));
the pattern is the constraint of that fold expanded constraint[.](#6.17.sentence-1)
[*Example [5](#example-5)*: template<class ... Types> void f(Types ... rest);template<class ... Types> void g(Types ... rest) { f(&rest ...); // “&rest ...'' is a pack expansion; “&rest'' is its pattern} — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3244)
For the purpose of determining whether a pack satisfies a rule
regarding entities other than packs, the pack is
considered to be the entity that would result from an instantiation of
the pattern in which it appears[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3250)
A pack whose name appears within the pattern of a pack
expansion is expanded by that pack expansion[.](#8.sentence-1)
An appearance of the name of
a pack is only expanded by the innermost enclosing pack expansion[.](#8.sentence-2)
The pattern of a pack expansion shall name one or more packs that
are not expanded by a nested pack expansion; such packs are called[*unexpanded packs*](#def:pack,unexpanded "13.7.4Variadic templates[temp.variadic]") in the pattern[.](#8.sentence-3)
All of the packs expanded
by a pack expansion shall have the same number of arguments specified[.](#8.sentence-4)
An
appearance of a name of a pack that is not expanded is
ill-formed[.](#8.sentence-5)
[*Example [6](#example-6)*: template<typename...> struct Tuple {};template<typename T1, typename T2> struct Pair {};
template<class ... Args1> struct zip {template<class ... Args2> struct with {typedef Tuple<Pair<Args1, Args2> ... > type; };};
typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>typedef zip<short>::with<unsigned short, unsigned>::type T2; // error: different number of arguments specified for Args1 and Args2template<class ... Args>void g(Args ... args) { // OK, Args is expanded by the function parameter pack args f(const_cast<const Args*>(&args)...); // OK, “Args'' and “args'' are expanded f(5 ...); // error: pattern does not contain any packs f(args); // error: pack “args'' is not expanded f(h(args ...) + args ...); // OK, first “args'' expanded within h,// second “args'' expanded within f} — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3287)
The instantiation of a pack expansion considers
items E1,E2,…,EN,
whereN is the number of elements in the pack expansion parameters[.](#9.sentence-1)
Each Ei is generated by instantiating the pattern and
replacing each pack expansion parameter with its ith element[.](#9.sentence-2)
Such an element, in the context of the instantiation, is interpreted as
follows:
- [(9.1)](#9.1)
if the pack is a template parameter pack, the element is
* [(9.1.1)](#9.1.1)
a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") for a type template parameter pack,
* [(9.1.2)](#9.1.2)
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") for a constant template parameter pack, or
* [(9.1.3)](#9.1.3)
a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") for a template template parameter pack
designating the ith corresponding
type, constant, or template template argument;
- [(9.2)](#9.2)
if the pack is a function parameter pack, the element is an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") designating the ith function parameter
that resulted from instantiation of
the function parameter pack declaration;
- [(9.3)](#9.3)
if the pack is an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack,
the element is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") designating the variable introduced by
the ith [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") that resulted from instantiation of
the [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3Captures[expr.prim.lambda.capture]") pack declaration;
otherwise
- [(9.4)](#9.4)
if the pack is a structured binding pack,
the element is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") designating the ith structured binding in the pack
that resulted from the structured binding declaration.
When N is zero, the instantiation of a pack expansion
does not alter the syntactic interpretation of the enclosing construct,
even in cases where omitting the pack expansion entirely would
otherwise be ill-formed or would result in an ambiguity in the grammar[.](#9.sentence-4)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3338)
The instantiation of a sizeof... expression ([[expr.sizeof]](expr.sizeof "7.6.2.5Sizeof")) produces
an integral constant with value N[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3342)
When instantiating a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4Pack indexing expression[expr.prim.pack.index]") P,
let K be the index of P[.](#11.sentence-1)
The instantiation of P is the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") EK[.](#11.sentence-2)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3347)
When instantiating a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") P,
let K be the index of P[.](#12.sentence-1)
The instantiation of P is the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") EK[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3352)
The instantiation of an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") with an ellipsis
produces E1 E2 … EN[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3356)
The instantiation of a [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7Fold expressions[expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7Fold expressions")) produces:
- [(14.1)](#14.1)
( ((E1*op* E2)*op* ⋯)*op* EN) for a unary left fold,
- [(14.2)](#14.2)
( E1 *op*(⋯ *op*(EN−1 *op*EN))) for a unary right fold,
- [(14.3)](#14.3)
( (((E*op* E1)*op* E2)*op* ⋯)*op* EN) for a binary left fold, and
- [(14.4)](#14.4)
( E1 *op*(⋯ *op*(EN−1 *op*(EN *op*E)))) for a binary right fold[.](#14.sentence-1)
In each case,*op* is the [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7Fold expressions[expr.prim.fold]")[.](#14.sentence-2)
For a binary fold,E is generated
by instantiating the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") that did not contain an unexpanded pack[.](#14.sentence-3)
[*Example [7](#example-7)*: template<typename ...Args>bool all(Args ...args) { return (... && args); }bool b = all(true, true, true, false);
Within the instantiation of all,
the returned expression expands to((true && true) && true) && false,
which evaluates to false[.](#14.sentence-4)
— *end example*]
If N is zero for a unary fold,
the value of the expression is shown in Table [20](#tab:temp.fold.empty "Table 20: Value of folding empty sequences");
if the operator is not listed in Table [20](#tab:temp.fold.empty "Table 20: Value of folding empty sequences"),
the instantiation is ill-formed[.](#14.sentence-5)
Table [20](#tab:temp.fold.empty) — Value of folding empty sequences [[tab:temp.fold.empty]](./tab:temp.fold.empty)
| [🔗](#tab:temp.fold.empty-row-1)<br>**Operator** | **Value when pack is empty** |
| --- | --- |
| [🔗](#tab:temp.fold.empty-row-2)<br>&& | true |
| [🔗](#tab:temp.fold.empty-row-3)<br>|| | false |
| [🔗](#tab:temp.fold.empty-row-4)<br>, | void() |
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3430)
A fold expanded constraint is not instantiated ([[temp.constr.fold]](temp.constr.fold "13.5.2.5Fold expanded constraint"))[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L3433)
The instantiation of any other pack expansion
produces a list of elements E1,E2,…,EN[.](#16.sentence-1)
[*Note [1](#note-1)*:
The variety of list varies with the context:[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]"),[*template-argument-list*](temp.names#nt:template-argument-list "13.3Names of template specializations[temp.names]"), etc[.](#16.sentence-2)
— *end note*]
When N is zero, the instantiation of the expansion produces an empty list[.](#16.sentence-3)
[*Example [8](#example-8)*: template<class... T> struct X : T... { };template<class... T> void f(T... values) { X<T...> x(values...);}template void f<>(); // OK, X<> has no base classes// x is a variable of type X<> that is value-initialized — *end example*]