Init
This commit is contained in:
85
cppdraft/temp/alias.md
Normal file
85
cppdraft/temp/alias.md
Normal 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.1 Preamble [temp.pre]") in which the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") is an[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")) declares the[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") to be an [*alias template*](#def:template,alias "13.7.8 Alias 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.3 Names 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.3 Names of template specializations [temp.names]") that is not the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names of template specializations [temp.names]")*s* for the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* in the [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") of
|
||||
the alias template[.](#2.sentence-1)
|
||||
|
||||
Any other [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") that names a specialization of an alias template is
|
||||
a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The 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.3 Names of template specializations [temp.names]") is dependent, subsequent template
|
||||
argument substitution still applies to the [*template-id*](temp.names#nt:template-id "13.3 Names 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.2 Type 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.1 General [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.1 General [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
483
cppdraft/temp/arg.md
Normal 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.3 Names of template specializations [temp.names]") specified
|
||||
in a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") or
|
||||
in a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.1 Preamble [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.4 Variadic templates [temp.variadic]"), it will correspond to zero or more[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.1 Preamble [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.1 Preamble [temp.pre]")[.](#general-2.sentence-1)
|
||||
|
||||
If the nth template parameter is
|
||||
a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.3 Names of template specializations [temp.names]"),
|
||||
an ambiguity between a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") and an expression is resolved to a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),
|
||||
regardless of the form of the corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.3 Names 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.3 Names 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.3 Names 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.7 Destructors")) 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.3 Names 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.3 Names 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.3 Names of template specializations [temp.names]")*s* do not match the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.2 Template 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.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") does not designate a function,
|
||||
a default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is[implicitly instantiated](temp.inst "13.9.2 Implicit 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.3 Names of template specializations [temp.names]") followed by an ellipsis is
|
||||
a [pack expansion](temp.variadic#def:pack_expansion "13.7.4 Variadic 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.3 Names of template specializations [temp.names]") because the form of the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") determines the allowable forms of the[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.3 Names of template specializations [temp.names]") for a type template parameter
|
||||
shall be a[*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 General"))[.](#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.6 The constexpr and consteval specifiers"))[.](#nontype-1.sentence-1)
|
||||
|
||||
If T contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||||
or a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced 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.3 Names of template specializations [temp.names]") or
|
||||
(for a default template argument) an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.2 Template 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.1 General [dcl.init.general]"),A shall be a converted constant expression ([[expr.const]](expr.const "7.7 Constant 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.1 General [expr.prim.id.general]") v is termed a [*candidate initializer*](#def:candidate_initializer "13.4.3 Constant 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.2 Template 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.1 General [dcl.decl.general]") for the initialization would not be a constant expression
|
||||
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ([[expr.const]](expr.const "7.7 Constant expressions")), or
|
||||
|
||||
- [(4.3)](#nontype-4.3)
|
||||
|
||||
the initialization would cause P to not be template-argument-equivalent ([[temp.type]](temp.type "13.6 Type 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.7 Temporary objects")),
|
||||
|
||||
- [(6.2)](#nontype-6.2)
|
||||
|
||||
a string literal object ([[lex.string]](lex.string "5.13.5 String literals")),
|
||||
|
||||
- [(6.3)](#nontype-6.3)
|
||||
|
||||
the result of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
|
||||
- [(6.4)](#nontype-6.4)
|
||||
|
||||
a predefined __func__ variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), or
|
||||
|
||||
- [(6.5)](#nontype-6.5)
|
||||
|
||||
a subobject ([[intro.object]](intro.object "6.8.2 Object 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.5 String literals [lex.string]") ([[lex.string]](lex.string "5.13.5 String literals")) is
|
||||
not an acceptable [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.3 Names 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.3 Names 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.5 String 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.3 Names 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.3 Names 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.2 Template 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.2 Template 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.2 Template 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.6 Partial 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.3 Names of template specializations [temp.names]") A are[*compatible*](#def:compatible,template_template_parameter_and_template_argument "13.4.4 Template 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.3 Names 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.1 Preamble [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.2 Function 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.1 Preamble [temp.pre]") contains a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") that declares a template parameter
|
||||
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Preamble [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.3 Names 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.3 Partial 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.1 Preamble [temp.pre]") of A (including default arguments
|
||||
and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 Preamble [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.2 Template parameters [temp.param]") PP in the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of the function template,
|
||||
a corresponding [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.4 Variadic templates"));
|
||||
otherwise, AA is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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)
|
||||
156
cppdraft/temp/arg/explicit.md
Normal file
156
cppdraft/temp/arg/explicit.md
Normal 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.3 Names of template specializations [temp.names]")*s* in the same way as[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.5 Constructors"), [[class.qual]](class.qual "6.5.5.2 Class 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.3 Template argument deduction")) or
|
||||
obtained from default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* may be omitted from the list of explicit [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*[.](#4.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A trailing template parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.3 Names 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.6 Functions")) 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.3 Names of template specializations [temp.names]")*s* than there are corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* unless one of the [*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.3 Standard 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.5 Constructors")) are named without using a
|
||||
function name ([[class.qual]](class.qual "6.5.5.2 Class 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*]
|
||||
154
cppdraft/temp/arg/general.md
Normal file
154
cppdraft/temp/arg/general.md
Normal 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.3 Names of template specializations [temp.names]") specified
|
||||
in a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") or
|
||||
in a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.1 Preamble [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.4 Variadic templates [temp.variadic]"), it will correspond to zero or more[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.1 Preamble [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.1 Preamble [temp.pre]")[.](#2.sentence-1)
|
||||
|
||||
If the nth template parameter is
|
||||
a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.3 Names of template specializations [temp.names]"),
|
||||
an ambiguity between a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") and an expression is resolved to a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),
|
||||
regardless of the form of the corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.3 Names 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.3 Names 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.3 Names 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.7 Destructors")) 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.3 Names 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.3 Names 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.3 Names of template specializations [temp.names]")*s* do not match the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.2 Template 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.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") does not designate a function,
|
||||
a default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") is[implicitly instantiated](temp.inst "13.9.2 Implicit 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.3 Names of template specializations [temp.names]") followed by an ellipsis is
|
||||
a [pack expansion](temp.variadic#def:pack_expansion "13.7.4 Variadic 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.3 Names of template specializations [temp.names]") because the form of the[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") determines the allowable forms of the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")[.](#footnote-109.sentence-1)
|
||||
177
cppdraft/temp/arg/nontype.md
Normal file
177
cppdraft/temp/arg/nontype.md
Normal 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.6 The constexpr and consteval specifiers"))[.](#1.sentence-1)
|
||||
|
||||
If T contains a placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||||
or a placeholder for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced 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.3 Names of template specializations [temp.names]") or
|
||||
(for a default template argument) an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.2 Template 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.1 General [dcl.init.general]"),A shall be a converted constant expression ([[expr.const]](expr.const "7.7 Constant 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.1 General [expr.prim.id.general]") v is termed a [*candidate initializer*](#def:candidate_initializer "13.4.3 Constant 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.2 Template 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.1 General [dcl.decl.general]") for the initialization would not be a constant expression
|
||||
when interpreted as a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ([[expr.const]](expr.const "7.7 Constant expressions")), or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
the initialization would cause P to not be template-argument-equivalent ([[temp.type]](temp.type "13.6 Type 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.7 Temporary objects")),
|
||||
|
||||
- [(6.2)](#6.2)
|
||||
|
||||
a string literal object ([[lex.string]](lex.string "5.13.5 String literals")),
|
||||
|
||||
- [(6.3)](#6.3)
|
||||
|
||||
the result of a typeid expression ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification")),
|
||||
|
||||
- [(6.4)](#6.4)
|
||||
|
||||
a predefined __func__ variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), or
|
||||
|
||||
- [(6.5)](#6.5)
|
||||
|
||||
a subobject ([[intro.object]](intro.object "6.8.2 Object 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.5 String literals [lex.string]") ([[lex.string]](lex.string "5.13.5 String literals")) is
|
||||
not an acceptable [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.3 Names 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.3 Names 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.5 String 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.3 Names 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*]
|
||||
137
cppdraft/temp/arg/template.md
Normal file
137
cppdraft/temp/arg/template.md
Normal 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.3 Names 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.2 Template 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.2 Template 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.2 Template 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.6 Partial 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.3 Names of template specializations [temp.names]") A are[*compatible*](#def:compatible,template_template_parameter_and_template_argument "13.4.4 Template 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.3 Names 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.1 Preamble [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.2 Function 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.1 Preamble [temp.pre]") contains a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") that declares a template parameter
|
||||
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Preamble [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.3 Names 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.3 Partial 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.1 Preamble [temp.pre]") of A (including default arguments
|
||||
and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 Preamble [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.2 Template parameters [temp.param]") PP in the [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") of the function template,
|
||||
a corresponding [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.4 Variadic templates"));
|
||||
otherwise, AA is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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
30
cppdraft/temp/arg/type.md
Normal 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.3 Names of template specializations [temp.names]") for a type template parameter
|
||||
shall be a[*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 General"))[.](#2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
229
cppdraft/temp/class.md
Normal file
229
cppdraft/temp/class.md
Normal 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.1 General [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.3 Simple 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.1 Preamble [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.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template 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.1 Preamble [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.1 Preamble [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.1 Preamble [class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated 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.3 Names 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.3 Names 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.3 Names 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.3 Names of template specializations [temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type 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.8 Deduced 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.9 Class 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.3 Deduction guides [temp.deduct.guide]")
|
||||
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.6 Functions [dcl.fct]") of a deduction guide
|
||||
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||||
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of
|
||||
a deduction guide[.](#temp.deduct.guide-3.sentence-1)
|
||||
|
||||
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.3 Names of template specializations [temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#temp.deduct.guide-3.sentence-3)
|
||||
|
||||
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3 Deduction 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.6 Functions [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.2 Implicit 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*]
|
||||
80
cppdraft/temp/class/general.md
Normal file
80
cppdraft/temp/class/general.md
Normal 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.1 General [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.3 Simple 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.1 Preamble [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.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template 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.1 Preamble [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.1 Preamble [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.1 Preamble [class.pre]") shall agree in kind with the original class template declaration ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers"))[.](#4.sentence-1)
|
||||
79
cppdraft/temp/concept.md
Normal file
79
cppdraft/temp/concept.md
Normal 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.9 Concept definitions [temp.concept]") is a template
|
||||
that defines constraints on its template arguments[.](#1.sentence-1)
|
||||
|
||||
[concept-definition:](#nt:concept-definition "13.7.9 Concept definitions [temp.concept]")
|
||||
concept [*concept-name*](#nt:concept-name "13.7.9 Concept definitions [temp.concept]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt = [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") ;
|
||||
|
||||
[concept-name:](#nt:concept-name "13.7.9 Concept definitions [temp.concept]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4698)
|
||||
|
||||
A [*concept-definition*](#nt:concept-definition "13.7.9 Concept definitions [temp.concept]") declares a concept[.](#2.sentence-1)
|
||||
|
||||
Its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") becomes a [*concept-name*](#nt:concept-name "13.7.9 Concept 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.1 Attribute 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.4 Concept 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.3 Constrained declarations [temp.constr.decl]") T f1(T x) { return x; }template<C T> // C, as a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.9 Concept definitions [temp.concept]") shall inhabit a namespace scope ([[basic.scope.namespace]](basic.scope.namespace "6.4.6 Namespace 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.3 Constrained 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.9 Template instantiation and specialization"))[.](#5.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A concept-id ([[temp.names]](temp.names "13.3 Names of template specializations")) is evaluated as an expression[.](#5.sentence-2)
|
||||
|
||||
A concept cannot be
|
||||
explicitly instantiated ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")),
|
||||
explicitly specialized ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")),
|
||||
or partially specialized ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial 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.3 Constrained declarations [temp.constr.decl]") of a [*concept-definition*](#nt:concept-definition "13.7.9 Concept definitions [temp.concept]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context 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.9 Concept definitions [temp.concept]")[.](#7.sentence-1)
|
||||
|
||||
A [*type concept*](#def:concept,type "13.7.9 Concept definitions [temp.concept]") is a concept whose prototype parameter
|
||||
is a type template parameter[.](#7.sentence-2)
|
||||
848
cppdraft/temp/constr.md
Normal file
848
cppdraft/temp/constr.md
Normal 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.2 Constraints")[.](#general-1.sentence-2)
|
||||
|
||||
Constraints are associated with declarations in [[temp.constr.decl]](#decl "13.5.3 Constrained declarations")[.](#general-1.sentence-3)
|
||||
|
||||
Declarations are partially ordered by their associated constraints ([[temp.constr.order]](#order "13.5.5 Partial 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.1 General [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.2 Logical operations")),
|
||||
|
||||
- [(1.2)](#constr.general-1.2)
|
||||
|
||||
disjunctions ([[temp.constr.op]](#op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.3)](#constr.general-1.3)
|
||||
|
||||
atomic constraints ([[temp.constr.atomic]](#atomic "13.5.2.3 Atomic constraints")),
|
||||
|
||||
- [(1.4)](#constr.general-1.4)
|
||||
|
||||
concept-dependent constraints ([[temp.constr.concept]](#concept "13.5.2.4 Concept-dependent constraints")), and
|
||||
|
||||
- [(1.5)](#constr.general-1.5)
|
||||
|
||||
fold expanded constraints ([[temp.constr.fold]](#fold "13.5.2.5 Fold 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.9 Template instantiation and specialization")),
|
||||
its [associated constraints](#def:associated_constraints "13.5.3 Constrained 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.3 Names of template specializations"))
|
||||
requires the satisfaction of its constraints[.](#constr.general-2.sentence-2)
|
||||
|
||||
[Overload resolution](over.match.viable "12.2.3 Viable 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.2 Logical 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.2 Logical 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.2 Logical 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.2 Logical 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.3 Constrained 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.2 Unary 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.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](#order "13.5.5 Partial 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.3 Atomic 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.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.3 Atomic 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.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](#decl "13.5.3 Constrained declarations"))[.](#atomic-1.sentence-1)
|
||||
|
||||
[*Note [1](#atomic-note-1)*:
|
||||
|
||||
Atomic constraints are formed by [constraint normalization](#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#atomic-1.sentence-2)
|
||||
|
||||
E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical 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.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to
|
||||
those mapped by the parameter mappings of the expression,
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.8 Alias 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.2 Function 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.3 Atomic 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.1 General")),
|
||||
the constraint is not satisfied[.](#atomic-3.sentence-2)
|
||||
|
||||
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-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.4 Concept-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.9 Concept 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.4 Concept-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.1 General")),
|
||||
the constraint is not satisfied[.](#concept-2.sentence-2)
|
||||
|
||||
Otherwise, let CIâ² be
|
||||
the normal form ([[temp.constr.normal]](#normal "13.5.4 Constraint 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.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and
|
||||
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold 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.4 Variadic templates"))[.](#fold-1.sentence-2)
|
||||
|
||||
Let N be the number of elements
|
||||
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.7 Fold 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.7 Fold 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.5 Fold expanded constraint [temp.constr.fold]") if their respective constraints both contain
|
||||
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.1 Preamble"))
|
||||
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))
|
||||
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.3 Constrained declarations [temp.constr.decl]")
|
||||
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15 Logical 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.2 Template parameters [temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") or parameter-type-list[.](#decl-2.sentence-1)
|
||||
|
||||
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained 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.3 Constrained 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.3 Constrained 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.3 Constrained declarations [temp.constr.decl]"),
|
||||
the associated constraints are the [normal form](#def:normal_form,constraint "13.5.4 Constraint 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.14 Logical 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.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")) in
|
||||
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]"),
|
||||
in order of appearance, and
|
||||
|
||||
* [(3.3.2)](#decl-3.3.2)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") following
|
||||
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")), and
|
||||
|
||||
* [(3.3.3)](#decl-3.3.3)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")) of
|
||||
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.2 Constraints"))[.](#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.3 Constrained 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.2 Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained 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.3 Constrained 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.3 Constrained 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.4 Constraint normalization [temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E is
|
||||
a [constraint](#def:constraint "13.5.2 Constraints [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.2 Logical 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.3 Constrained 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.3 Constrained 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.3 Constrained 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.7 Fold expressions [expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold 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.5 Fold expanded constraint")) whose
|
||||
constraint is Eâ² and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold 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.3 Constrained declarations [temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#normal-2.sentence-1)
|
||||
|
||||
[*Note [1](#normal-note-1)*:
|
||||
|
||||
Normalization of [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* is performed
|
||||
when determining the associated constraints ([[temp.constr.constr]](#constr "13.5.2 Constraints"))
|
||||
of a declaration
|
||||
and
|
||||
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5 Names"))[.](#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.5 Partial 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.3 Atomic 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.7 Fold 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.3 Atomic 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.4 Best viable function")),
|
||||
|
||||
- [(2.2)](#order-2.2)
|
||||
|
||||
the address of a non-template function ([[over.over]](over.over "12.3 Address of an overload set")),
|
||||
|
||||
- [(2.3)](#order-2.3)
|
||||
|
||||
the matching of template template arguments ([[temp.arg.template]](temp.arg.template "13.4.4 Template 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.3 Partial 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.3 Partial 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.5 Partial 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.5 Partial 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.5 Partial 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.5 Partial 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.6 Functions")), 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)
|
||||
87
cppdraft/temp/constr/atomic.md
Normal file
87
cppdraft/temp/constr/atomic.md
Normal 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.3 Atomic 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.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Atomic constraints are formed by [constraint normalization](temp.constr.normal#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#1.sentence-2)
|
||||
|
||||
E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical 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.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to
|
||||
those mapped by the parameter mappings of the expression,
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.8 Alias 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.2 Function 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.3 Atomic 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.1 General")),
|
||||
the constraint is not satisfied[.](#3.sentence-2)
|
||||
|
||||
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-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*]
|
||||
81
cppdraft/temp/constr/concept.md
Normal file
81
cppdraft/temp/constr/concept.md
Normal 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.4 Concept-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.9 Concept 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.4 Concept-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.1 General")),
|
||||
the constraint is not satisfied[.](#2.sentence-2)
|
||||
|
||||
Otherwise, let CIâ² be
|
||||
the normal form ([[temp.constr.normal]](temp.constr.normal "13.5.4 Constraint 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*]
|
||||
368
cppdraft/temp/constr/constr.md
Normal file
368
cppdraft/temp/constr/constr.md
Normal 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.1 General [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.2 Logical operations")),
|
||||
|
||||
- [(1.2)](#general-1.2)
|
||||
|
||||
disjunctions ([[temp.constr.op]](#temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.3)](#general-1.3)
|
||||
|
||||
atomic constraints ([[temp.constr.atomic]](#temp.constr.atomic "13.5.2.3 Atomic constraints")),
|
||||
|
||||
- [(1.4)](#general-1.4)
|
||||
|
||||
concept-dependent constraints ([[temp.constr.concept]](#temp.constr.concept "13.5.2.4 Concept-dependent constraints")), and
|
||||
|
||||
- [(1.5)](#general-1.5)
|
||||
|
||||
fold expanded constraints ([[temp.constr.fold]](#temp.constr.fold "13.5.2.5 Fold 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.9 Template instantiation and specialization")),
|
||||
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained 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.3 Names of template specializations"))
|
||||
requires the satisfaction of its constraints[.](#general-2.sentence-2)
|
||||
|
||||
[Overload resolution](over.match.viable "12.2.3 Viable 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.2 Logical 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.2 Logical 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.2 Logical 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.2 Logical 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.3 Constrained 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.2 Unary 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.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5 Partial 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.3 Atomic 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.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.3 Atomic 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.3 Atomic constraints [temp.constr.atomic]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained 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.4 Constraint normalization [temp.constr.normal]")[.](#temp.constr.atomic-1.sentence-2)
|
||||
|
||||
E is never a [logical and expression](expr.log.and "7.6.14 Logical AND operator [expr.log.and]") nor a [logical or expression](expr.log.or "7.6.15 Logical 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.3 Atomic constraints [temp.constr.atomic]") if they are formed from the same appearance of the same[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") and if, given a hypothetical template A whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") consists of[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* corresponding and equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading")) to
|
||||
those mapped by the parameter mappings of the expression,
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are
|
||||
the targets of the parameter mapping of e1 is the same ([[temp.type]](temp.type "13.6 Type equivalence")) as
|
||||
a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") naming A whose [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.8 Alias 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.2 Function 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.3 Atomic 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.1 General")),
|
||||
the constraint is not satisfied[.](#temp.constr.atomic-3.sentence-2)
|
||||
|
||||
Otherwise, the [lvalue-to-rvalue conversion](conv.lval "7.3.2 Lvalue-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.4 Concept-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.9 Concept 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.4 Concept-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.1 General")),
|
||||
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.4 Constraint 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.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and
|
||||
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold 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.4 Variadic 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.4 Variadic 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.7 Fold 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.7 Fold 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.5 Fold expanded constraint [temp.constr.fold]") if their respective constraints both contain
|
||||
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#temp.constr.fold-5.sentence-1)
|
||||
60
cppdraft/temp/constr/constr/general.md
Normal file
60
cppdraft/temp/constr/constr/general.md
Normal 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.1 General [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.2 Logical operations")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
disjunctions ([[temp.constr.op]](temp.constr.op "13.5.2.2 Logical operations")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
atomic constraints ([[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints")),
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
concept-dependent constraints ([[temp.constr.concept]](temp.constr.concept "13.5.2.4 Concept-dependent constraints")), and
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
fold expanded constraints ([[temp.constr.fold]](temp.constr.fold "13.5.2.5 Fold 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.9 Template instantiation and specialization")),
|
||||
its [associated constraints](temp.constr.decl#def:associated_constraints "13.5.3 Constrained 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.3 Names of template specializations"))
|
||||
requires the satisfaction of its constraints[.](#2.sentence-2)
|
||||
|
||||
[Overload resolution](over.match.viable "12.2.3 Viable functions [over.match.viable]") requires the satisfaction of constraints
|
||||
on functions and function templates[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
129
cppdraft/temp/constr/decl.md
Normal file
129
cppdraft/temp/constr/decl.md
Normal 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.1 Preamble"))
|
||||
or templated function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))
|
||||
can be constrained by the use of a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")[.](#1.sentence-1)
|
||||
|
||||
This allows the specification of constraints for that declaration as
|
||||
an expression:
|
||||
|
||||
[constraint-expression:](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")
|
||||
[*logical-or-expression*](expr.log.or#nt:logical-or-expression "7.6.15 Logical 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.2 Template parameters [temp.param]")*s* in a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") or parameter-type-list[.](#2.sentence-1)
|
||||
|
||||
Each of these forms introduces additional [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained 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.3 Constrained declarations [temp.constr.decl]") are defined as follows:
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
If there are no introduced [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained 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.3 Constrained declarations [temp.constr.decl]"),
|
||||
the associated constraints are the [normal form](temp.constr.normal#def:normal_form,constraint "13.5.4 Constraint 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.14 Logical 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.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")) in
|
||||
the declaration's [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]"),
|
||||
in order of appearance, and
|
||||
|
||||
* [(3.3.2)](#3.3.2)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") following
|
||||
a [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")), and
|
||||
|
||||
* [(3.3.3)](#3.3.3)
|
||||
|
||||
the [*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
each [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.3 Constrained declarations [temp.constr.decl]") introduced by
|
||||
a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")) of
|
||||
a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.2 Constraints"))[.](#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.3 Constrained 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.2 Function template overloading")) to the corresponding[*constraint-expression*](#nt:constraint-expression "13.5.3 Constrained 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.3 Constrained 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.3 Constrained declarations [temp.constr.decl]") for the specialization,
|
||||
so it does match #2[.](#4.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
63
cppdraft/temp/constr/fold.md
Normal file
63
cppdraft/temp/constr/fold.md
Normal 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.5 Fold expanded constraint [temp.constr.fold]") is formed from a constraint C and
|
||||
a [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold 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.4 Variadic templates"))[.](#1.sentence-2)
|
||||
|
||||
Let N be the number of elements
|
||||
in the pack expansion parameters ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.7 Fold 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.7 Fold 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.5 Fold expanded constraint [temp.constr.fold]") if their respective constraints both contain
|
||||
an equivalent unexpanded pack ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#5.sentence-1)
|
||||
24
cppdraft/temp/constr/general.md
Normal file
24
cppdraft/temp/constr/general.md
Normal 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.5 Template 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.2 Constraints")[.](#1.sentence-2)
|
||||
|
||||
Constraints are associated with declarations in [[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations")[.](#1.sentence-3)
|
||||
|
||||
Declarations are partially ordered by their associated constraints ([[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints"))[.](#1.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
190
cppdraft/temp/constr/normal.md
Normal file
190
cppdraft/temp/constr/normal.md
Normal 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.4 Constraint normalization [temp.constr.normal]") of an [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") E is
|
||||
a [constraint](temp.constr.constr#def:constraint "13.5.2 Constraints [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.2 Logical 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.3 Constrained 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.3 Constrained 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.3 Constrained 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.7 Fold expressions [expr.prim.fold]") Op ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold 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.5 Fold expanded constraint")) whose
|
||||
constraint is Eâ² and whose [*fold-operator*](expr.prim.fold#nt:fold-operator "7.5.7 Fold 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.3 Constrained declarations [temp.constr.decl]") is called[*normalization*](#def:constraint,normalization "13.5.4 Constraint normalization [temp.constr.normal]")[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Normalization of [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* is performed
|
||||
when determining the associated constraints ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||||
of a declaration
|
||||
and
|
||||
when evaluating the value of an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") that names a concept specialization ([[expr.prim.id]](expr.prim.id "7.5.5 Names"))[.](#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
105
cppdraft/temp/constr/op.md
Normal 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.2 Logical 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.2 Logical 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.2 Logical 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.2 Logical 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.3 Constrained 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.2 Unary 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.3 Constrained declarations [temp.constr.decl]")*s* that are equivalent under [[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading") do not subsume one another under [[temp.constr.order]](temp.constr.order "13.5.5 Partial 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.3 Atomic 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.3 Atomic constraints"))// are not formed from the same [*expression*](expr.comma#nt:expression "7.6.20 Comma 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*]
|
||||
157
cppdraft/temp/constr/order.md
Normal file
157
cppdraft/temp/constr/order.md
Normal 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.5 Partial 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.3 Atomic 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.7 Fold 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.3 Atomic 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.4 Best viable function")),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
the address of a non-template function ([[over.over]](over.over "12.3 Address of an overload set")),
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
the matching of template template arguments ([[temp.arg.template]](temp.arg.template "13.4.4 Template template arguments")),
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
the partial ordering of class template specializations ([[temp.spec.partial.order]](temp.spec.partial.order "13.7.6.3 Partial ordering of partial specializations")), and
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
the partial ordering of function templates ([[temp.func.order]](temp.func.order "13.7.7.3 Partial 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.5 Partial 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.5 Partial 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.5 Partial 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.5 Partial 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.6 Functions")), 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
1903
cppdraft/temp/decls.md
Normal file
File diff suppressed because it is too large
Load Diff
63
cppdraft/temp/decls/general.md
Normal file
63
cppdraft/temp/decls/general.md
Normal 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.1 General [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.3 Names 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.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template 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.3 Names of template specializations [temp.names]") is
|
||||
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial 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.2 Template parameters [temp.param]")*s*,[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* ([[temp.pre]](temp.pre "13.1 Preamble")),
|
||||
and[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.2 Template parameters [temp.param]"),[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"),
|
||||
or[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.2 Template parameters [temp.param]")*s*,[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*,
|
||||
or[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.2 The 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.4 Compound statement or block [stmt.block]") of an [*expansion-statement*](stmt.expand#nt:expansion-statement "8.7 Expansion 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.1 Preamble [dcl.pre]") cannot declare a[*template-id*](temp.names#nt:template-id "13.3 Names 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
1462
cppdraft/temp/deduct.md
Normal file
File diff suppressed because it is too large
Load Diff
208
cppdraft/temp/deduct/call.md
Normal file
208
cppdraft/temp/deduct/call.md
Normal 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<Pâ²> 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.5 List-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.6 Deducing 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.6 Functions [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.1 General [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.6 Deducing 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.3 Array-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.4 Function-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.2 Deducing 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.9 Class 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.14 Function pointer conversions [conv.fctptr]") and/or[qualification conversion](conv.qual "7.3.6 Qualification 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.3 Names of template specializations [temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names of template specializations [temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names of template specializations [temp.names]") cannot be deduced from a function call and the[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.2 Constraints")) 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.2 Placeholder 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*]
|
||||
93
cppdraft/temp/deduct/conv.md
Normal file
93
cppdraft/temp/deduct/conv.md
Normal 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.3 Conversion functions [class.conv.fct]") of the[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") being looked up
|
||||
(call it A) as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#1.sentence-1)
|
||||
|
||||
If the [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") is constructed during
|
||||
overload resolution ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate 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.3 Array-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.4 Function-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.5 Exception 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)
|
||||
41
cppdraft/temp/deduct/decl.md
Normal file
41
cppdraft/temp/deduct/decl.md
Normal 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.1 General [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.3 Explicit instantiation [temp.explicit]"), [explicit specializations](temp.expl.spec "13.9.4 Explicit specialization [temp.expl.spec]"),
|
||||
and certain [friend declarations](temp.friend "13.7.5 Friends [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.3 Deallocation functions"), [[expr.new]](expr.new "7.6.2.8 New"))[.](#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.8 New")[.](#1.sentence-4)
|
||||
|
||||
The
|
||||
deduction is done as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6 Deducing 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.3 Partial ordering of function templates")),
|
||||
deduction fails and, in the declaration cases, the
|
||||
program is ill-formed[.](#2.sentence-1)
|
||||
35
cppdraft/temp/deduct/funcaddr.md
Normal file
35
cppdraft/temp/deduct/funcaddr.md
Normal 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.3 Address 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.6 Deducing 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.7 Placeholder 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)
|
||||
368
cppdraft/temp/deduct/general.md
Normal file
368
cppdraft/temp/deduct/general.md
Normal 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.3 Names 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.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is not valid ([[temp.names]](temp.names "13.3 Names 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.6 Functions") 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.3 Constrained declarations")),
|
||||
those constraints are checked for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#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.1 General [temp.deduct.general]") are
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"),
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function 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.1 General"))[.](#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.5 Exception specifications"))
|
||||
and function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
is done only when
|
||||
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [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.1 General [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.3 Qualified names [expr.prim.id.qual]") of a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.2 Closure 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.5 List-initialization [dcl.init.list]") would be required
|
||||
to convert the [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.3 Constant 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*]
|
||||
57
cppdraft/temp/deduct/guide.md
Normal file
57
cppdraft/temp/deduct/guide.md
Normal 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.3 Names of template specializations [temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type 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.8 Deduced 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.9 Class 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.3 Deduction guides [temp.deduct.guide]")
|
||||
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.6 Functions [dcl.fct]") of a deduction guide
|
||||
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||||
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of
|
||||
a deduction guide[.](#3.sentence-1)
|
||||
|
||||
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") shall name a class template specialization[.](#3.sentence-2)
|
||||
|
||||
The [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#3.sentence-3)
|
||||
|
||||
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3 Deduction 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.6 Functions [dcl.fct]")*s* if either is reachable from the other[.](#3.sentence-5)
|
||||
219
cppdraft/temp/deduct/partial.md
Normal file
219
cppdraft/temp/deduct/partial.md
Normal 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.3 Partial 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.3 Partial 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.6 Deducing 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.1 General [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.5 Deducing 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.5 Deducing 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)
|
||||
540
cppdraft/temp/deduct/type.md
Normal file
540
cppdraft/temp/deduct/type.md
Normal 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.2 Deducing 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.3 Qualified 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.3 Qualified 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.4 Pack indexing specifier [dcl.type.pack.index]") or a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]")[.](#5.2.sentence-1)
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
A [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#5.3.sentence-1)
|
||||
|
||||
- [(5.4)](#5.4)
|
||||
|
||||
The [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")[.](#5.4.sentence-1)
|
||||
|
||||
- [(5.5)](#5.5)
|
||||
|
||||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Address of an overload set"))
|
||||
after template argument deduction has succeeded ([[temp.over]](temp.over "13.10.4 Overload 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.5 List-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.2 Deducing 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.6 Functions [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.5 Exception specifications"))
|
||||
in which the (possibly-implicit, see [[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.5 Deducing 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.6 Functions")) 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.3 Deducing 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.7 Deducing 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.2 Deducing 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.6 Functions [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.1 General [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.5 Deducing 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.3 Names 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.5 Exception 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.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names 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.2 Template 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.3 Names 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.3 Names 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.4 Variadic 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.3 Names 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
829
cppdraft/temp/dep.md
Normal 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.1 General [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.1 General [temp.dep.general]") (that is, its type may depend on a template parameter) or[*value-dependent*](#def:expression,value-dependent "13.8.3.1 General [temp.dep.general]") (that is, its value when evaluated as a constant expression ([[expr.const]](expr.const "7.7 Constant 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.1 General [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.3 Operators in expressions")),
|
||||
of the form:
|
||||
|
||||
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
|
||||
where the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified 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.1 General [expr.post.general]") is a pack
|
||||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), or
|
||||
|
||||
- [(2.2)](#general-2.2)
|
||||
|
||||
any of the expressions
|
||||
or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s* in the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is [type-dependent](#expr "13.8.3.3 Type-dependent expressions [temp.dep.expr]"), or
|
||||
|
||||
- [(2.3)](#general-2.3)
|
||||
|
||||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.2 Unqualified names [expr.prim.id.unqual]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified 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.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion 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.2 Unqualified names [expr.prim.id.unqual]") is
|
||||
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [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.1 Point 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.2 Candidate 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.2 Template 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.3 Names of template specializations [temp.names]") refers to the[*current instantiation*](#def:current_instantiation "13.8.3.2 Dependent 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.1 Preamble [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.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template 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.6 Partial 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.6 Local 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.11 Identifiers [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.11 Identifiers [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.2 Dependent 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.5 Qualified name lookup")) or unqualified name is a[*member of the current instantiation*](#def:current_instantiation,member_of_the "13.8.3.2 Dependent 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.2 Dependent 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.10 The 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.5 Qualified 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.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion 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.5 Qualified 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.1 General") â *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.1 Sequential 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.1 General")) 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.8 Deduced 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.2 Type names [dcl.name]") is dependent after
|
||||
class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction"))
|
||||
and substitution ([[temp.alias]](temp.alias "13.7.8 Alias 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.3 Names 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.7 Dependent 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.4 Pack indexing specifier [dcl.type.pack.index]"),
|
||||
|
||||
- [(10.13)](#type-10.13)
|
||||
|
||||
denoted by decltype([*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")),
|
||||
where [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is [type-dependent](#expr "13.8.3.3 Type-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.9 Type splicing [dcl.type.splice]") in which either
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5 Dependent 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.1 Preamble")) of a class template
|
||||
used without a [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names 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.3 This")) is
|
||||
dependent ([[temp.dep.type]](#type "13.8.3.2 Dependent 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.1 General [expr.prim.id.general]") is type-dependent
|
||||
if it is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.7 Placeholder 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.7 Placeholder 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.7 Structured binding declarations")) whose[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.3 Captures"))
|
||||
in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") that has an explicit object parameter whose type is dependent ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(3.8)](#expr-3.8)
|
||||
|
||||
the[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")__func__ ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), 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.2 Referring 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.3 Conversion 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.1 Preamble [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.7 Expansion 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.5 Static 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.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||||
or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") is dependent, even if any subexpression is type-dependent:
|
||||
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.1 Kinds of literals [lex.literal.kinds]")
|
||||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
|
||||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||||
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||||
throw [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")opt
|
||||
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
[*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")
|
||||
[*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")
|
||||
|
||||
[*Note [1](#expr-note-1)*:
|
||||
|
||||
For the standard library macro offsetof,
|
||||
see [[support.types]](support.types "17.2 Common 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.5 Class 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.1 General [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.1 General [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.7 Fold 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.4 Pack indexing expression [expr.prim.pack.index]") is type-dependent
|
||||
if its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.9 Expression splicing [expr.prim.splice]") is type-dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5 Dependent 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.1 General [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.9 Concept definitions [temp.concept]") is dependent or
|
||||
any of its arguments are dependent ([[temp.dep.temp]](#temp "13.8.3.7 Dependent 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.1 Preamble [stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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.1 General [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.7 Constant 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.1 General [expr.unary.general]") or [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is type-dependent or the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") is dependent:
|
||||
|
||||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
|
||||
[*Note [1](#constexpr-note-1)*:
|
||||
|
||||
For the standard library macro offsetof,
|
||||
see [[support.types]](support.types "17.2 Common 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.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"), or[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") is dependent or the[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") or[*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") is value-dependent or
|
||||
any [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is value-dependent or
|
||||
any [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") is value-dependent:
|
||||
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.11 Identifiers [lex.name]") )
|
||||
[*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]")
|
||||
|
||||
unless the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.7 noexcept operator [expr.unary.noexcept]") ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))
|
||||
is value-dependent if
|
||||
its [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.3 Qualified names [expr.prim.id.qual]") where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.3 Explicit type conversion (cast notation) [expr.cast]") is also value-dependent if evaluating [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") as a [core constant expression](expr.const#def:expression,core_constant "7.7 Constant 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.10 The 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.10 The reflection operator [expr.reflect]") and
|
||||
the [*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The 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.1 General [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.2 Dependent types")),
|
||||
|
||||
- [(7.2)](#constexpr-7.2)
|
||||
|
||||
it is of the form ^^[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") and
|
||||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 General [expr.prim.id.general]") and
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.9 Expression splicing [expr.prim.splice]") is value-dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](#splice "13.8.3.5 Dependent 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.6 Splice specifiers [basic.splice]") is dependent
|
||||
if its converted [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is value-dependent[.](#splice-1.sentence-1)
|
||||
|
||||
A [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") is dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Namespace alias [namespace.alias]") whose [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]") (if any) is
|
||||
a dependent qualified name or
|
||||
whose [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") (if any) is dependent[.](#namespace-1.sentence-1)
|
||||
|
||||
A [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [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.3 Names 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.3 Names 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.3 Names 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.3 Names 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)
|
||||
82
cppdraft/temp/dep/candidate.md
Normal file
82
cppdraft/temp/dep/candidate.md
Normal 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.3 Dependent 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.4 Argument-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*]
|
||||
163
cppdraft/temp/dep/constexpr.md
Normal file
163
cppdraft/temp/dep/constexpr.md
Normal 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.1 General [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.9 Concept definitions [temp.concept]") is dependent or
|
||||
any of its arguments are dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7 Dependent 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.1 Preamble [stmt.pre]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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.1 General [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.7 Constant 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.1 General [expr.unary.general]") or [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is type-dependent or the[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") is dependent:
|
||||
|
||||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
For the standard library macro offsetof,
|
||||
see [[support.types]](support.types "17.2 Common 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.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"), or[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") is dependent or the[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") or[*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") is value-dependent or
|
||||
any [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") in the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is value-dependent or
|
||||
any [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") in the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") is value-dependent:
|
||||
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.11 Identifiers [lex.name]") )
|
||||
[*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]")
|
||||
|
||||
unless the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.7 noexcept operator [expr.unary.noexcept]") ([[expr.unary.noexcept]](expr.unary.noexcept "7.6.2.7 noexcept operator"))
|
||||
is value-dependent if
|
||||
its [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.3 Qualified names [expr.prim.id.qual]") where the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.3 Explicit type conversion (cast notation) [expr.cast]") is also value-dependent if evaluating [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]") as a [core constant expression](expr.const#def:expression,core_constant "7.7 Constant 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.10 The 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.10 The reflection operator [expr.reflect]") and
|
||||
the [*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The 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.1 General [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.2 Dependent types")),
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
it is of the form ^^[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") and
|
||||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 General [expr.prim.id.general]") and
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.9 Expression splicing [expr.prim.splice]") is value-dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#8.sentence-1)
|
||||
198
cppdraft/temp/dep/expr.md
Normal file
198
cppdraft/temp/dep/expr.md
Normal 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.3 This")) is
|
||||
dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent 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.1 General [expr.prim.id.general]") is type-dependent
|
||||
if it is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.7 Placeholder 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.7 Placeholder 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.7 Structured binding declarations")) whose[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.3 Captures"))
|
||||
in a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") that has an explicit object parameter whose type is dependent ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(3.8)](#3.8)
|
||||
|
||||
the[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")__func__ ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), 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.2 Referring 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.3 Conversion 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.1 Preamble [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.7 Expansion 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.5 Static 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.2 Type names [dcl.name]"),[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),
|
||||
or[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") is dependent, even if any subexpression is type-dependent:
|
||||
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||||
::opt new [*new-placement*](expr.new#nt:new-placement "7.6.2.8 New [expr.new]")opt ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]")opt
|
||||
dynamic_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
static_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
const_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
reinterpret_cast < [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") > ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.1 Kinds of literals [lex.literal.kinds]")
|
||||
sizeof [*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")
|
||||
sizeof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
sizeof ... ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
|
||||
alignof ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
typeid ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
typeid ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") )
|
||||
::opt delete [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||||
::opt delete [ ] [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit type conversion (cast notation) [expr.cast]")
|
||||
throw [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")opt
|
||||
noexcept ( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") )
|
||||
[*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]")
|
||||
[*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
For the standard library macro offsetof,
|
||||
see [[support.types]](support.types "17.2 Common 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.5 Class 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.1 General [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.1 General [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.7 Fold 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.4 Pack indexing expression [expr.prim.pack.index]") is type-dependent
|
||||
if its [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.9 Expression splicing [expr.prim.splice]") is type-dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers"))[.](#9.sentence-1)
|
||||
94
cppdraft/temp/dep/general.md
Normal file
94
cppdraft/temp/dep/general.md
Normal 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.1 General [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.1 General [temp.dep.general]") (that is, its type may depend on a template parameter) or[*value-dependent*](#def:expression,value-dependent "13.8.3.1 General [temp.dep.general]") (that is, its value when evaluated as a constant expression ([[expr.const]](expr.const "7.7 Constant 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.1 General [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.3 Operators in expressions")),
|
||||
of the form:
|
||||
|
||||
[*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
|
||||
where the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [expr.post.general]") is an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified 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.1 General [expr.post.general]") is a pack
|
||||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")), or
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
any of the expressions
|
||||
or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s* in the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") is [type-dependent](temp.dep.expr "13.8.3.3 Type-dependent expressions [temp.dep.expr]"), or
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.2 Unqualified names [expr.prim.id.unqual]") ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names"))
|
||||
is dependent if
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
it is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion 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.2 Unqualified names [expr.prim.id.unqual]") is
|
||||
the [*postfix-expression*](expr.post.general#nt:postfix-expression "7.6.1.1 General [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.1 Point 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.2 Candidate 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.2 Template parameters [temp.param]")[.](#3.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
27
cppdraft/temp/dep/namespace.md
Normal file
27
cppdraft/temp/dep/namespace.md
Normal 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.3 Namespace alias [namespace.alias]") whose [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]") (if any) is
|
||||
a dependent qualified name or
|
||||
whose [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") (if any) is dependent[.](#1.sentence-1)
|
||||
|
||||
A [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [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
206
cppdraft/temp/dep/res.md
Normal 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.5 Exception 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.5 Exception 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.5 Exception 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.5 Exception specifications [except.spec]") immediately follows the namespace
|
||||
scope declaration or definition that requires the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.1 Preamble [dcl.pre]") of the[*translation-unit*](basic.link#nt:translation-unit "6.7 Program and linkage [basic.link]"),
|
||||
prior to the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") (if any),
|
||||
the point after the [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]") of the [*translation-unit*](basic.link#nt:translation-unit "6.7 Program 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.5 Private 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.3 One-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.4 Compound statement or block [stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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.3 Dependent 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.4 Argument-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*]
|
||||
39
cppdraft/temp/dep/splice.md
Normal file
39
cppdraft/temp/dep/splice.md
Normal 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.6 Splice specifiers [basic.splice]") is dependent
|
||||
if its converted [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is value-dependent[.](#1.sentence-1)
|
||||
|
||||
A [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") is dependent
|
||||
if its [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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
44
cppdraft/temp/dep/temp.md
Normal 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.3 Names 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.3 Names 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.3 Names 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.3 Names 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
306
cppdraft/temp/dep/type.md
Normal 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.3 Names of template specializations [temp.names]") refers to the[*current instantiation*](#def:current_instantiation "13.8.3.2 Dependent 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.1 Preamble [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.1 Preamble [temp.pre]") ([[temp.arg]](temp.arg "13.4 Template 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.6 Partial 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.6 Local 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.11 Identifiers [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.11 Identifiers [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.2 Dependent 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.5 Qualified name lookup")) or unqualified name is a[*member of the current instantiation*](#def:current_instantiation,member_of_the "13.8.3.2 Dependent 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.2 Dependent 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.10 The 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.5 Qualified 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.3 Conversion functions [class.conv.fct]") whose [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion 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.5 Qualified 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.1 General") â *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.1 Sequential 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.1 General")) 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.8 Deduced 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.2 Type names [dcl.name]") is dependent after
|
||||
class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction"))
|
||||
and substitution ([[temp.alias]](temp.alias "13.7.8 Alias 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.3 Names 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.7 Dependent 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.4 Pack indexing specifier [dcl.type.pack.index]"),
|
||||
|
||||
- [(10.13)](#10.13)
|
||||
|
||||
denoted by decltype([*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")),
|
||||
where [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is [type-dependent](temp.dep.expr "13.8.3.3 Type-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.9 Type splicing [dcl.type.splice]") in which either
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is dependent ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent 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.1 Preamble")) of a class template
|
||||
used without a [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]")[.](#footnote-118.sentence-1)
|
||||
380
cppdraft/temp/expl/spec.md
Normal file
380
cppdraft/temp/expl/spec.md
Normal 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.4 Explicit specialization [temp.expl.spec]")
|
||||
template < > [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [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.2 Explicit template argument specification"))
|
||||
|
||||
Given these declarations,
|
||||
#1 will be used as the definition of streams ofchars;
|
||||
other streams will be handled by class template specializations instantiated
|
||||
from the class template[.](#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.1 Preamble [dcl.pre]") in an [*explicit-specialization*](#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") shall not be an [*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")[.](#2.sentence-1)
|
||||
|
||||
An explicit specialization shall not use
|
||||
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers"))
|
||||
other than thread_local[.](#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.4 Meaning of declarators"), [[class.mem]](class.mem "11.4 Class members"), [[temp.mem]](temp.mem "13.7.3 Member 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.1 General"))[.](#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.4 Special 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.9 Types"))[.](#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.3 Constrained 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.3 Names of template specializations")),
|
||||
or, for explicit specializations of function templates,
|
||||
during template argument deduction ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration"))
|
||||
when one or more trailing template arguments are left unspecified[.](#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.7 Function 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.1 General [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.4 Explicit type conversion (functional notation)")):template<> X Q<int>::x; // declarationtemplate<> X Q<int>::x (); // error: declares a functiontemplate<> X Q<int>::x = X(); // definition
|
||||
|
||||
â *end note*]
|
||||
|
||||
[14](#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.1 Preamble [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.2 Template parameters [temp.param]")*s* in the[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") shall be the same as those specified in the primary template definition[.](#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
214
cppdraft/temp/explicit.md
Normal 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.3 Explicit instantiation [temp.explicit]")
|
||||
externopt template [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")
|
||||
|
||||
There are two forms of explicit instantiation: an explicit instantiation
|
||||
definition and an explicit instantiation declaration[.](#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.2 Storage class specifiers [dcl.stc]") ([[dcl.stc]](dcl.stc "9.2.2 Storage 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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"))
|
||||
shall appertain to an explicit instantiation[.](#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.5 Elaborated type specifiers [dcl.type.elab]") in the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") shall include a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]");
|
||||
otherwise, the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") shall be a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") whose [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") comprises a single [*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [dcl.decl.general]") that does not have an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")[.](#4.sentence-1)
|
||||
|
||||
If the explicit instantiation is for a variable template specialization,
|
||||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") in the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#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.2 Explicit 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.1 General"))[.](#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.1 Preamble [dcl.pre]") of the explicit instantiation names an implicitly-declared special member
|
||||
function ([[special]](special "11.4.4 Special member functions")), the program is ill-formed[.](#5.sentence-4)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6985)
|
||||
|
||||
The [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") and
|
||||
the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") produced by the corresponding substitution
|
||||
into the templated function, variable, or class
|
||||
are two declarations of the same entity[.](#6.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
These declarations need to have matching types as specified in [[basic.link]](basic.link "6.7 Program and linkage"), except as specified in [[except.spec]](except.spec "14.5 Exception specifications")[.](#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.7 Placeholder type specifiers")) â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
Despite its syntactic form, the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in an [*explicit-instantiation*](#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable[.](#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.3 Constrained 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.3 Names of template specializations")),
|
||||
or, for explicit instantiations of function templates,
|
||||
during template argument deduction ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration"))
|
||||
when one or more trailing template arguments are left unspecified[.](#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.3 Constrained declarations"), [[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")),
|
||||
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.7 Destructors"))
|
||||
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.2 Implicit instantiation [temp.inst]") in the translation unit
|
||||
shall be the subject of an explicit instantiation definition somewhere in the
|
||||
program; otherwise the program is ill-formed, no diagnostic required[.](#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
520
cppdraft/temp/fct.md
Normal 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.6 Functions")) 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.3 One-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.3 One-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 "3 Terms 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.2 Function template overloading [temp.over.link]") if two function definitions containing the expressions would satisfy
|
||||
the [one-definition rule](basic.def.odr "6.3 One-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.3 Names of template specializations")) may differ
|
||||
as long as the two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* are the same ([[temp.type]](temp.type "13.6 Type 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.1 General [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.1 General [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.3 Dependent 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.1 General"))[.](#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.2 Function 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.1 Preamble [temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if
|
||||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||||
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are equivalent
|
||||
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* that are equivalent
|
||||
if either [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||||
and if either [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"),
|
||||
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are equivalent[.](#temp.over.link-6.sentence-1)
|
||||
|
||||
Two [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2 Function 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.2 Template 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.1 Preamble [temp.pre]")*s* are equivalent[.](#temp.over.link-6.sentence-2)
|
||||
|
||||
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 Preamble [temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||||
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.1 General")),
|
||||
|
||||
- [(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.7 Program 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.3 Template 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.3 Partial 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.4 Best 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.3 Deallocation functions"), [[expr.new]](expr.new "7.6.2.8 New"));
|
||||
|
||||
- [(1.4)](#temp.func.order-1.4)
|
||||
|
||||
when a [friend function declaration](temp.friend "13.7.5 Friends [temp.friend]"), an[explicit instantiation](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]") or an [explicit specialization](temp.expl.spec "13.9.4 Explicit 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.4 Variadic 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.1 Preamble [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.3 Operators 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.1 General [dcl.decl.general]") ofM is && or
|
||||
if M has no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [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.5 Deducing 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.1 Preamble [temp.pre]")*s* (possibly including [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* invented for an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))) 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.1 Preamble [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.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [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.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* are not equivalent ([[temp.over.link]](#temp.over.link "13.7.7.2 Function 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.5 Partial 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*]
|
||||
49
cppdraft/temp/fct/general.md
Normal file
49
cppdraft/temp/fct/general.md
Normal 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.6 Functions")) 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.3 One-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
1750
cppdraft/temp/fct/spec.md
Normal file
File diff suppressed because it is too large
Load Diff
34
cppdraft/temp/fct/spec/general.md
Normal file
34
cppdraft/temp/fct/spec/general.md
Normal 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.3 Template 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
149
cppdraft/temp/friend.md
Normal 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.3 Names 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.3 Names 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.4 Meaning of declarators")),
|
||||
in which case they are attached to
|
||||
the same module as the class template ([[module.unit]](module.unit "10.1 Module 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.2 Implicit instantiation")), partially
|
||||
specialized ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")) or explicitly specialized ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit 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.5 Elaborated type specifiers [dcl.type.elab]"),
|
||||
in either case with a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ending with a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]"), *C*,
|
||||
whose [*template-name*](temp.names#nt:template-name "13.3 Names 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.6 Deducing 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.3 Names 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.1 Preamble [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
253
cppdraft/temp/func/order.md
Normal 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.3 Template 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.3 Partial 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.4 Best 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.3 Deallocation functions"), [[expr.new]](expr.new "7.6.2.8 New"));
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
when a [friend function declaration](temp.friend "13.7.5 Friends [temp.friend]"), an[explicit instantiation](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]") or an [explicit specialization](temp.expl.spec "13.9.4 Explicit 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.4 Variadic 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.1 Preamble [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.3 Operators 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.1 General [dcl.decl.general]") ofM is && or
|
||||
if M has no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [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.5 Deducing 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.1 Preamble [temp.pre]")*s* (possibly including [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* invented for an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))) 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.1 Preamble [temp.pre]") such that
|
||||
- [(8.2.1.2.1)](#8.2.1.2.1)
|
||||
|
||||
the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [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.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* are not equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.5 Partial 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
412
cppdraft/temp/inst.md
Normal file
@@ -0,0 +1,412 @@
|
||||
[temp.inst]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.9 Template instantiation and specialization [[temp.spec]](temp.spec#temp.inst)
|
||||
|
||||
### 13.9.2 Implicit instantiation [temp.inst]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6485)
|
||||
|
||||
A template specialization E is a [*declared specialization*](#def:specialization,declared "13.9.2 Implicit instantiation [temp.inst]") if there is a reachable
|
||||
explicit instantiation definition ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")) or
|
||||
explicit specialization declaration ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization"))
|
||||
for E, or
|
||||
if there is a reachable explicit instantiation declaration for E andE is not
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
an inline function,
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
declared with a type deduced
|
||||
from its initializer or return value ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
a potentially-constant variable ([[expr.const]](expr.const "7.7 Constant expressions")), or
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
a specialization of a templated class[.](#1.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An implicit instantiation in an importing translation unit
|
||||
cannot use names with internal linkage
|
||||
from an imported translation unit ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#1.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6510)
|
||||
|
||||
Unless a class template specialization is a declared specialization,
|
||||
the class template specialization is implicitly instantiated when the
|
||||
specialization is referenced in a context that requires a completely-defined
|
||||
object type or when the completeness of the class type affects the semantics
|
||||
of the program[.](#2.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
In particular, if the semantics of an expression depend on the member or
|
||||
base class lists of a class template specialization, the class template
|
||||
specialization is implicitly generated[.](#2.sentence-2)
|
||||
|
||||
For instance, deleting a pointer
|
||||
to class type depends on whether or not the class declares a destructor,
|
||||
and a conversion between pointers to class type depends on the
|
||||
inheritance relationship between the two classes involved[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: template<class T> class B { /* ... */ };template<class T> class D : public B<T> { /* ... */ };
|
||||
|
||||
void f(void*);void f(B<int>*);
|
||||
|
||||
void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); // instantiation of D<int> required: call f(B<int>*) B<char>* q = pp; // instantiation of D<char> required: convert D<char>* to B<char>*delete ppp; // instantiation of D<double> required} â *end example*]
|
||||
|
||||
If the template selected for the specialization ([[temp.spec.partial.match]](temp.spec.partial.match "13.7.6.2 Matching of partial specializations"))
|
||||
has been declared, but not defined,
|
||||
at the point of instantiation ([[temp.point]](temp.point "13.8.4.1 Point of instantiation")),
|
||||
the instantiation yields an incomplete class type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1 General"))[.](#2.sentence-4)
|
||||
|
||||
[*Example [2](#example-2)*: template<class T> class X;
|
||||
X<char> ch; // error: incomplete type X<char> â *end example*]
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Within a template declaration,
|
||||
a [local class](class.local "11.6 Local class declarations [class.local]") or enumeration and the members of
|
||||
a local class are never considered to be entities that can be separately
|
||||
instantiated (this includes their default arguments,[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s*, and non-static data member
|
||||
initializers, if any,
|
||||
but not their [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* or [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*)[.](#2.sentence-5)
|
||||
|
||||
As a result, the dependent names are looked up, the
|
||||
semantic constraints are checked, and any templates used are instantiated as
|
||||
part of the instantiation of the entity within which the local class or
|
||||
enumeration is declared[.](#2.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6564)
|
||||
|
||||
The implicit instantiation of a class template specialization causes
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
the implicit instantiation of the declarations, but not of the definitions,
|
||||
of the non-deleted
|
||||
class member functions,
|
||||
member classes,
|
||||
scoped member enumerations,
|
||||
static data members,
|
||||
member templates, and
|
||||
friends; and
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
the implicit instantiation of the definitions of
|
||||
deleted member functions,
|
||||
unscoped member enumerations, and
|
||||
member anonymous unions[.](#3.sentence-1)
|
||||
|
||||
The implicit instantiation of a class template specialization
|
||||
does not cause the implicit instantiation of
|
||||
default arguments or [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of the class member functions[.](#3.sentence-2)
|
||||
|
||||
[*Example [3](#example-3)*: template<class T>struct C {void f() { T x; }void g() = delete;};
|
||||
C<void> c; // OK, definition of C<void>::f is not instantiated at this pointtemplate<> void C<int>::g() { } // error: redefinition of C<int>::g â *end example*]
|
||||
|
||||
However, for the purpose of determining whether an instantiated redeclaration
|
||||
is valid according to [[basic.def.odr]](basic.def.odr "6.3 One-definition rule") and [[class.mem]](class.mem "11.4 Class members"),
|
||||
an instantiated declaration that corresponds to a definition in the template
|
||||
is considered to be a definition[.](#3.sentence-3)
|
||||
|
||||
[*Example [4](#example-4)*: template<class T, class U>struct Outer {template<class X, class Y> struct Inner; template<class Y> struct Inner<T, Y>; // #1atemplate<class Y> struct Inner<T, Y> { }; // #1b; OK, valid redeclaration of #1atemplate<class Y> struct Inner<U, Y> { }; // #2};
|
||||
|
||||
Outer<int, int> outer; // error at #2
|
||||
|
||||
Outer<int, int>::Inner<int, Y> is redeclared at #1b[.](#3.sentence-4)
|
||||
|
||||
(It is not defined
|
||||
but noted as being associated with a definition in Outer<T, U>[.](#3.sentence-5))
|
||||
|
||||
#2
|
||||
is also a redeclaration of #1a[.](#3.sentence-6)
|
||||
|
||||
It is noted as associated with a definition,
|
||||
so it is an invalid redeclaration of the same partial specialization[.](#3.sentence-7)
|
||||
|
||||
template<typename T> struct Friendly {template<typename U> friend int f(U) { return sizeof(T); }};
|
||||
Friendly<char> fc;
|
||||
Friendly<float> ff; // error: produces second definition of f(U) â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6628)
|
||||
|
||||
Unless a member of a templated class is a declared specialization,
|
||||
the specialization of the member is implicitly instantiated when the
|
||||
specialization is referenced in a context that requires the member definition
|
||||
to exist or
|
||||
if the existence of the definition of the member
|
||||
affects the semantics of the program;
|
||||
in particular, the initialization (and any associated side effects) of a
|
||||
static data member does not occur unless the static data member is itself used
|
||||
in a way that requires the definition of the static data member to exist[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6639)
|
||||
|
||||
Unless a function template specialization is a declared specialization,
|
||||
the function template specialization is implicitly instantiated when the
|
||||
specialization is referenced in a context that requires a function definition
|
||||
to exist or
|
||||
if the existence of the definition affects the semantics of the program[.](#5.sentence-1)
|
||||
|
||||
A function whose declaration was instantiated from a friend function definition is
|
||||
implicitly instantiated when it is referenced in a context that
|
||||
requires a function definition to exist or
|
||||
if the existence of the definition affects the semantics of the program[.](#5.sentence-2)
|
||||
|
||||
Unless a call is to a function template explicit specialization or
|
||||
to a member function of an explicitly specialized class template,
|
||||
a default argument for a function template or a member function of a
|
||||
class template is implicitly instantiated when the function is
|
||||
called in a context that requires the value of the default argument[.](#5.sentence-3)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
An inline function
|
||||
that is the subject of an explicit instantiation declaration
|
||||
is not a declared specialization;
|
||||
the intent is that it still be implicitly instantiated
|
||||
when odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule"))
|
||||
so that the body can be considered for inlining,
|
||||
but that no out-of-line copy of it be generated in the translation unit[.](#5.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6664)
|
||||
|
||||
[*Example [5](#example-5)*: template<class T> struct Z {void f(); void g();};
|
||||
|
||||
void h() { Z<int> a; // instantiation of class Z<int> required Z<char>* p; // instantiation of class Z<char> not required Z<double>* q; // instantiation of class Z<double> not required a.f(); // instantiation of Z<int>::f() required p->g(); // instantiation of class Z<char> required, and// instantiation of Z<char>::g() required}
|
||||
|
||||
Nothing in this example requiresclassZ<double>,Z<int>::g(),
|
||||
orZ<char>::f() to be implicitly instantiated[.](#6.sentence-1)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6692)
|
||||
|
||||
Unless a variable template specialization is a declared specialization,
|
||||
the variable template specialization is implicitly instantiated
|
||||
when it is referenced in a context
|
||||
that requires a variable definition to exist or
|
||||
if the existence of the definition affects the semantics of the program[.](#7.sentence-1)
|
||||
|
||||
A default template argument for a variable template is implicitly instantiated
|
||||
when the variable template is referenced in a context
|
||||
that requires the value of the default argument[.](#7.sentence-2)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6702)
|
||||
|
||||
The existence of a definition of a variable or function
|
||||
is considered to affect the semantics of the program
|
||||
if the variable or function
|
||||
is needed for constant evaluation by an expression ([[expr.const]](expr.const "7.7 Constant expressions")),
|
||||
even if constant evaluation of the expression is not required or
|
||||
if constant expression evaluation does not use the definition[.](#8.sentence-1)
|
||||
|
||||
[*Example [6](#example-6)*: template<typename T> constexpr int f() { return T::value; }template<bool B, typename T> void g(decltype(B ? f<T>() : 0));template<bool B, typename T> void g(...);template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0}));template<bool B, typename T> void h(...);void x() { g<false, int>(0); // OK, B ? f<T>() : 0 is not potentially constant evaluated h<false, int>(0); // error, instantiates f<int> even though B evaluates to false and// list-initialization of int from int cannot be narrowing} â *end example*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6729)
|
||||
|
||||
If the function selected by [overload resolution](over.match "12.2 Overload resolution [over.match]") can be determined without instantiating a class template definition,
|
||||
it is unspecified whether that instantiation actually takes place[.](#9.sentence-1)
|
||||
|
||||
[*Example [7](#example-7)*: template <class T> struct S {operator int();};
|
||||
|
||||
void f(int);void f(S<int>&);void f(S<float>);
|
||||
|
||||
void g(S<int>& sr) { f(sr); // instantiation of S<int> allowed but not required// instantiation of S<float> allowed but not required}; â *end example*]
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6750)
|
||||
|
||||
If a function template or a member function template specialization is used in
|
||||
a way that involves overload resolution,
|
||||
a declaration of the specialization is implicitly instantiated ([[temp.over]](temp.over "13.10.4 Overload resolution"))[.](#10.sentence-1)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6755)
|
||||
|
||||
An implementation shall not implicitly instantiate a function template,
|
||||
a variable template,
|
||||
a member template, a non-virtual member function, a member class or
|
||||
static data member of a templated class, or a substatement of a constexpr if
|
||||
statement ([[stmt.if]](stmt.if "8.5.2 The if statement")), unless such instantiation is required[.](#11.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The instantiation of a generic lambda
|
||||
does not require instantiation of
|
||||
substatements of a constexpr if statement
|
||||
within its [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") unless the call operator template is instantiated[.](#11.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
It is unspecified whether or not an implementation implicitly instantiates a
|
||||
virtual member function of a class template if the virtual member function would
|
||||
not otherwise be instantiated[.](#11.sentence-3)
|
||||
|
||||
The use of a template specialization in
|
||||
a default argument or default member initializer
|
||||
shall not cause the template to be implicitly instantiated except
|
||||
where needed to determine
|
||||
the correctness of the default argument or default member initializer[.](#11.sentence-4)
|
||||
|
||||
The use of a default argument in a
|
||||
function call causes specializations in the default argument to be implicitly
|
||||
instantiated[.](#11.sentence-5)
|
||||
|
||||
Similarly, the use of a default member initializer
|
||||
in a constructor definition or an aggregate initialization
|
||||
causes specializations in the default member initializer to be instantiated[.](#11.sentence-6)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6783)
|
||||
|
||||
If a templated functionf is called in a way that requires a default argument to be used,
|
||||
the dependent names are looked up, the semantics constraints are checked,
|
||||
and the instantiation of any template used in the default argument
|
||||
is done as if the default argument had been
|
||||
an initializer used in a function template specialization with the same scope,
|
||||
the same template parameters and the same access as that of the function templatef used at that point, except that the scope in which a closure type is
|
||||
declared ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")) â and therefore its associated namespaces â
|
||||
remain as determined from the context of the definition for the default
|
||||
argument[.](#12.sentence-1)
|
||||
|
||||
This analysis is called[*default argument instantiation*](#def:default_argument_instantiation "13.9.2 Implicit instantiation [temp.inst]")[.](#12.sentence-2)
|
||||
|
||||
The instantiated default argument is then used as the argument off[.](#12.sentence-3)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6802)
|
||||
|
||||
Each default argument is instantiated independently[.](#13.sentence-1)
|
||||
|
||||
[*Example [8](#example-8)*: template<class T> void f(T x, T y = ydef(T()), T z = zdef(T()));
|
||||
|
||||
class A { };
|
||||
|
||||
A zdef(A);
|
||||
|
||||
void g(A a, A b, A c) { f(a, b, c); // no default argument instantiation f(a, b); // default argument z = zdef(T()) instantiated f(a); // error: ydef is not declared} â *end example*]
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6820)
|
||||
|
||||
The [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") and [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")*s* of a function template specialization
|
||||
are not instantiated along with the function declaration;
|
||||
they are instantiated
|
||||
when needed ([[except.spec]](except.spec "14.5 Exception specifications"), [[dcl.contract.func]](dcl.contract.func "9.4.1 General"))[.](#14.sentence-1)
|
||||
|
||||
If such a
|
||||
specifier is needed but has not yet been
|
||||
instantiated, the dependent names are looked up, the semantics constraints are
|
||||
checked, and the instantiation of any template used in the
|
||||
specifier is done as if it were being done as part
|
||||
of instantiating the declaration of the specialization at that point[.](#14.sentence-2)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6832)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
[[temp.point]](temp.point "13.8.4.1 Point of instantiation") defines the point of instantiation of a template specialization[.](#15.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6837)
|
||||
|
||||
There is an implementation-defined quantity
|
||||
that specifies the limit on the total depth of recursive instantiations ([[implimits]](implimits "Annex B (informative) Implementation quantities")),
|
||||
which could involve more than one template[.](#16.sentence-1)
|
||||
|
||||
The result of an infinite recursion in instantiation is undefined[.](#16.sentence-2)
|
||||
|
||||
[*Example [9](#example-9)*: template<class T> class X { X<T>* p; // OK X<T*> a; // implicit generation of X<T> requires// the implicit instantiation of X<T*> which requires// the implicit instantiation of X<T**> which …}; â *end example*]
|
||||
|
||||
[17](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L6853)
|
||||
|
||||
The [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* and [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of a template specialization or member function
|
||||
are not instantiated along with the specialization or function itself,
|
||||
even for a member function of a local class;
|
||||
substitution into the atomic constraints formed from them is instead performed
|
||||
as specified in [[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations") and [[temp.constr.atomic]](temp.constr.atomic "13.5.2.3 Atomic constraints") when determining whether the constraints are satisfied
|
||||
or as specified in [[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations") when comparing declarations[.](#17.sentence-1)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
The satisfaction of constraints is determined during
|
||||
template argument deduction ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")) and
|
||||
overload resolution ([[over.match]](over.match "12.2 Overload resolution"))[.](#17.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [10](#example-10)*: template<typename T> concept C = sizeof(T) > 2;template<typename T> concept D = C<T> && sizeof(T) > 4;
|
||||
|
||||
template<typename T> struct S { S() requires C<T> { } // #1 S() requires D<T> { } // #2};
|
||||
|
||||
S<char> s1; // error: no matching constructor S<char[8]> s2; // OK, calls #2
|
||||
|
||||
When S<char> is instantiated, both constructors are part of the
|
||||
specialization[.](#17.sentence-3)
|
||||
|
||||
Their constraints are not satisfied, and
|
||||
they suppress the implicit declaration of a default constructor forS<char> ([[class.default.ctor]](class.default.ctor "11.4.5.2 Default constructors")), so there is no viable constructor
|
||||
for s1[.](#17.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [11](#example-11)*: template<typename T> struct S1 {template<typename U>requires falsestruct Inner1; // ill-formed, no diagnostic required};
|
||||
|
||||
template<typename T> struct S2 {template<typename U>requires (sizeof(T[-(int)sizeof(T)]) > 1)struct Inner2; // ill-formed, no diagnostic required};
|
||||
|
||||
The class S1<T>::Inner1 is ill-formed, no diagnostic required, because
|
||||
it has no valid specializations[.](#17.sentence-5)
|
||||
|
||||
S2 is ill-formed, no diagnostic required, since no substitution into
|
||||
the constraints of its Inner2 template would result in a valid
|
||||
expression[.](#17.sentence-6)
|
||||
|
||||
â *end example*]
|
||||
118
cppdraft/temp/local.md
Normal file
118
cppdraft/temp/local.md
Normal 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.1 Preamble"))[.](#1.sentence-1)
|
||||
|
||||
The
|
||||
injected-class-name can be used
|
||||
as a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")[.](#1.sentence-2)
|
||||
|
||||
When it is used with a[*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]"),
|
||||
as a [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.5 Elaborated type specifiers [dcl.type.elab]") of
|
||||
a friend class template declaration,
|
||||
it is a [*template-name*](temp.names#nt:template-name "13.3 Names 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.3 Simple type specifiers [dcl.type.simple]") equivalent to the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") followed by
|
||||
the template argument list ([[temp.decls.general]](temp.decls.general "13.7.1 General"), [[temp.arg.general]](temp.arg.general "13.4.1 General"))
|
||||
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.3 Simple type specifiers [dcl.type.simple]"),
|
||||
it is equivalent to the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") followed by the[*template-argument*](temp.names#nt:template-argument "13.3 Names 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.3 Names of template specializations [temp.names]") or a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple 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.2 Member 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.3 Names 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.1 Preamble [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.1 Preamble [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.2 Dependent types"), [[class.member.lookup]](class.member.lookup "6.5.2 Member 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
103
cppdraft/temp/mem.md
Normal 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.1 Preamble [temp.pre]") equivalent to that
|
||||
of the class template followed by
|
||||
a [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") equivalent to that
|
||||
of the member template ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.8 Member 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.6 Functions")) 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.3 Conversion 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.9 Expression splicing [expr.prim.splice]")[.](#5.sentence-2)
|
||||
|
||||
There is no analogous syntax to form a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") ([[temp.names]](temp.names "13.3 Names of template specializations"))
|
||||
for such a function
|
||||
by providing an explicit template argument list ([[temp.arg.explicit]](temp.arg.explicit "13.10.2 Explicit template argument specification"))[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
27
cppdraft/temp/mem/class.md
Normal file
27
cppdraft/temp/mem/class.md
Normal 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.2 Implicit 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
19
cppdraft/temp/mem/enum.md
Normal 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
49
cppdraft/temp/mem/func.md
Normal 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.3 Names 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.3 Names 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.3 Names 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
258
cppdraft/temp/names.md
Normal 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.9 Template instantiation and specialization [temp.spec]") can be referred to by a[*template-id*](#nt:template-id "13.3 Names of template specializations [temp.names]"):
|
||||
|
||||
[simple-template-id:](#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*template-name*](#nt:template-name "13.3 Names of template specializations [temp.names]") < [*template-argument-list*](#nt:template-argument-list "13.3 Names of template specializations [temp.names]")opt >
|
||||
|
||||
[template-id:](#nt:template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*simple-template-id*](#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]") < [*template-argument-list*](#nt:template-argument-list "13.3 Names of template specializations [temp.names]")opt >
|
||||
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-defined literals [over.literal]") < [*template-argument-list*](#nt:template-argument-list "13.3 Names of template specializations [temp.names]")opt >
|
||||
|
||||
[template-name:](#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[template-argument-list:](#nt:template-argument-list "13.3 Names of template specializations [temp.names]")
|
||||
[*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]") ...opt
|
||||
[*template-argument-list*](#nt:template-argument-list "13.3 Names of template specializations [temp.names]") , [*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]") ...opt
|
||||
|
||||
[template-argument:](#nt:template-argument "13.3 Names of template specializations [temp.names]")
|
||||
[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")
|
||||
[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*template-name*](#nt:template-name "13.3 Names 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.3 Names of template specializations [temp.names]"),[*template-id*](#nt:template-id "13.3 Names of template specializations [temp.names]"), or[*template-name*](#nt:template-name "13.3 Names 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.3 Names of template specializations [temp.names]") if either
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
it follows a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Conversion 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.3 Qualified 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.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")),
|
||||
in a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning 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.3 Qualified names [expr.prim.id.qual]") ([[temp.res]](temp.res "13.8 Name resolution"))[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
If the name is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),
|
||||
it is then interpreted as a [*template-name*](#nt:template-name "13.3 Names 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.2 Dependent 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.3 Names 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.3 Names of template specializations [temp.names]") and completes
|
||||
the [*template-id*](#nt:template-id "13.3 Names of template specializations [temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names of template specializations [temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.7 Constant expressions [expr.const]") of a [*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]") shall not be an unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression 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.9 Expression 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.9 template 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.3 Names 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.3 Names of template specializations [temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is [*valid*](#def:template-id,valid "13.3 Names 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.4 Variadic 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.3 Names of template specializations [temp.names]"),
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
each [*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]") matches the corresponding
|
||||
template parameter ([[temp.arg]](temp.arg "13.4 Template 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.3 Names of template specializations [temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") shall be valid unless its respective[*template-name*](#nt:template-name "13.3 Names of template specializations [temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") names or designates a function template ([[temp.deduct]](temp.deduct "13.10.3 Template 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.3 Names of template specializations [temp.names]") of a [*simple-template-id*](#nt:simple-template-id "13.3 Names of template specializations [temp.names]") or
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") designates a constrained non-function template
|
||||
or
|
||||
a constrained template template parameter,
|
||||
and
|
||||
all [*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* in the [*simple-template-id*](#nt:simple-template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") are non-dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7 Dependent template arguments")),
|
||||
the associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))
|
||||
of the constrained template
|
||||
shall be satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#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.3 Names of template specializations [temp.names]") is a [*simple-template-id*](#nt:simple-template-id "13.3 Names of template specializations [temp.names]") where the [*template-name*](#nt:template-name "13.3 Names of template specializations [temp.names]") is a [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept 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.3 Constrained declarations [temp.constr.decl]") ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations"))
|
||||
is satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints")) 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.3 Constrained declarations [temp.constr.decl]") is an unevaluated operand,
|
||||
a concept-id appearing in a [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained 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.2 Type names [dcl.name]") of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the [*template-argument*](#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* of a subsequent [*template-id*](#nt:template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
|
||||
is considered nested for the purpose of this description[.](#footnote-108.sentence-1)
|
||||
113
cppdraft/temp/over.md
Normal file
113
cppdraft/temp/over.md
Normal 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.3 Template argument deduction"))
|
||||
and checking of any explicit template arguments ([[temp.arg]](temp.arg "13.4 Template 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.3 Names 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.4 Best 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.1 Preamble"))[.](#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.4 Best 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
232
cppdraft/temp/over/link.md
Normal 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.3 One-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 "3 Terms 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.2 Function template overloading [temp.over.link]") if two function definitions containing the expressions would satisfy
|
||||
the [one-definition rule](basic.def.odr "6.3 One-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.3 Names of template specializations")) may differ
|
||||
as long as the two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* are the same ([[temp.type]](temp.type "13.6 Type 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.1 General [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.1 General [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.3 Dependent 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.1 General"))[.](#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.2 Function 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.1 Preamble [temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if
|
||||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||||
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are equivalent
|
||||
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* that are equivalent
|
||||
if either [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||||
and if either [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"),
|
||||
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are equivalent[.](#6.sentence-1)
|
||||
|
||||
Two [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2 Function 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.2 Template 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.1 Preamble [temp.pre]")*s* are equivalent[.](#6.sentence-2)
|
||||
|
||||
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 Preamble [temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||||
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.1 General")),
|
||||
|
||||
- [(7.3)](#7.3)
|
||||
|
||||
would declare the same entity,
|
||||
when considering A and B to correspond in that determination ([[basic.link]](basic.link "6.7 Program 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
424
cppdraft/temp/param.md
Normal 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.2 Template parameters [temp.param]")*s* is:
|
||||
|
||||
[template-parameter:](#nt:template-parameter "13.2 Template parameters [temp.param]")
|
||||
[*type-parameter*](#nt:type-parameter "13.2 Template parameters [temp.param]")
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||||
[*type-tt-parameter*](#nt:type-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
[*variable-tt-parameter*](#nt:variable-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
[*concept-tt-parameter*](#nt:concept-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
|
||||
[type-parameter:](#nt:type-parameter "13.2 Template parameters [temp.param]")
|
||||
[*type-parameter-key*](#nt:type-parameter-key "13.2 Template parameters [temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt
|
||||
[*type-parameter-key*](#nt:type-parameter-key "13.2 Template parameters [temp.param]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt = [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")
|
||||
[*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt
|
||||
[*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt = [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")
|
||||
|
||||
[type-parameter-key:](#nt:type-parameter-key "13.2 Template parameters [temp.param]")
|
||||
class
|
||||
typename
|
||||
|
||||
[type-constraint:](#nt:type-constraint "13.2 Template parameters [temp.param]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") < [*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names of template specializations [temp.names]")opt >
|
||||
|
||||
[type-tt-parameter:](#nt:type-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") [*type-parameter-key*](#nt:type-parameter-key "13.2 Template parameters [temp.param]") ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt
|
||||
[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") [*type-parameter-key*](#nt:type-parameter-key "13.2 Template parameters [temp.param]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt [*type-tt-parameter-default*](#nt:type-tt-parameter-default "13.2 Template parameters [temp.param]")
|
||||
|
||||
[type-tt-parameter-default:](#nt:type-tt-parameter-default "13.2 Template parameters [temp.param]")
|
||||
= [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
= [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
[variable-tt-parameter:](#nt:variable-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") auto ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt
|
||||
[*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") auto [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt = [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
[concept-tt-parameter:](#nt:concept-tt-parameter "13.2 Template parameters [temp.param]")
|
||||
template < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") > concept ...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt
|
||||
template < [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") > concept [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt = [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
The component names of a [*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") are
|
||||
its [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") and
|
||||
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified 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.1 Preamble [temp.pre]") of a[*type-tt-parameter*](#nt:type-tt-parameter "13.2 Template parameters [temp.param]"),[*variable-tt-parameter*](#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"), or[*concept-tt-parameter*](#nt:concept-tt-parameter "13.2 Template parameters [temp.param]") can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3 Names 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.2 Template parameters [temp.param]") is
|
||||
a template parameter introduced by a [*type-parameter*](#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#2.1.sentence-1)
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
A [*constant template parameter*](#def:template_parameter,constant "13.2 Template parameters [temp.param]") is
|
||||
a template parameter introduced by a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#2.2.sentence-1)
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
A [*type template template parameter*](#def:template_parameter,type_template "13.2 Template parameters [temp.param]") is
|
||||
a template parameter introduced by a [*type-tt-parameter*](#nt:type-tt-parameter "13.2 Template parameters [temp.param]")[.](#2.3.sentence-1)
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
A [*variable template template parameter*](#def:template_parameter,variable_template "13.2 Template parameters [temp.param]") is
|
||||
a template parameter introduced by a [*variable-tt-parameter*](#nt:variable-tt-parameter "13.2 Template parameters [temp.param]")[.](#2.4.sentence-1)
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
A [*concept template parameter*](#def:template_parameter,concept "13.2 Template parameters [temp.param]") is
|
||||
a template parameter introduced by a [*concept-tt-parameter*](#nt:concept-tt-parameter "13.2 Template 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.2 Template 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.3 Qualified names [expr.prim.id.qual]") of a [*type-constraint*](#nt:type-constraint "13.2 Template 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.3 Constrained 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.2 Template parameters [temp.param]") is
|
||||
a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") that declares a pack ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")), or
|
||||
otherwise has an ellipsis prior to its optional [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),
|
||||
then the [*template-parameter*](#nt:template-parameter "13.2 Template parameters [temp.param]") declares a template parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#6.sentence-1)
|
||||
|
||||
A template parameter pack that is a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [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.1 Preamble [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.2 Template 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.1 Preamble [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.2 Template parameters [temp.param]")[.](#7.sentence-1)
|
||||
|
||||
typename followed by an[*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified 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.3 Qualified names [expr.prim.id.qual]") denotes the type in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#7.sentence-3)
|
||||
|
||||
A [*template-parameter*](#nt:template-parameter "13.2 Template parameters [temp.param]") of the formclass [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is a [*type-parameter*](#nt:type-parameter "13.2 Template 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.6 Functions [dcl.fct]") of a [*template-parameter*](#nt:template-parameter "13.2 Template parameters [temp.param]") shall not have a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage 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.11 Identifiers [lex.name]") in
|
||||
a [*template-parameter*](#nt:template-parameter "13.2 Template parameters [temp.param]") denoting a type or template
|
||||
is not looked up[.](#8.sentence-1)
|
||||
|
||||
An [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.4 The typedef specifier [dcl.typedef]") for a [*type-parameter*](#nt:type-parameter "13.2 Template parameters [temp.param]"),
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") for a [*variable-tt-parameter*](#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"),
|
||||
|
||||
- [(8.3)](#8.3)
|
||||
|
||||
a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") for a [*type-tt-parameter*](#nt:type-tt-parameter "13.2 Template parameters [temp.param]"), or
|
||||
|
||||
- [(8.4)](#8.4)
|
||||
|
||||
a [*concept-name*](temp.concept#nt:concept-name "13.7.9 Concept definitions [temp.concept]") for a [*concept-tt-parameter*](#nt:concept-tt-parameter "13.2 Template 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.2 Template 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.3 Constrained 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.3 Constrained declarations [temp.constr.decl]") E is called the[*immediately-declared constraint*](#def:constraint,immediately-declared "13.2 Template parameters [temp.param]") of Q for T[.](#9.sentence-5)
|
||||
|
||||
The concept designated by a [*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") shall be a type concept ([[temp.concept]](temp.concept "13.7.9 Concept definitions"))[.](#9.sentence-6)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L449)
|
||||
|
||||
A [*type-parameter*](#nt:type-parameter "13.2 Template parameters [temp.param]") that starts with a [*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") introduces the immediately-declared constraint
|
||||
of the [*type-constraint*](#nt:type-constraint "13.2 Template 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.7 Placeholder 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.8 Deduced class template specialization types"))[.](#11.sentence-1)
|
||||
|
||||
The top-level[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* on the[*template-parameter*](#nt:template-parameter "13.2 Template 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.2 Template 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.1 General [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.2 Template parameters [temp.param]"),
|
||||
which is template-argument-equivalent ([[temp.type]](temp.type "13.6 Type 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.3 Constant 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.1 General [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.2 Unqualified 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.2 Template parameters [temp.param]") introduces the immediately-declared constraint
|
||||
of the [*type-constraint*](#nt:type-constraint "13.2 Template parameters [temp.param]") for the invented type corresponding to the placeholder ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.2 Template parameters [temp.param]") is
|
||||
a template argument ([[temp.arg]](temp.arg "13.4 Template arguments")) specified after = in a [*template-parameter*](#nt:template-parameter "13.2 Template 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.4 Variadic 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.1 Preamble [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.7 Default 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.2 Template 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.2 Template 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.2 Template 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.2 Template parameters [temp.param]")[.](#19.sentence-2)
|
||||
|
||||
If a [*template-parameter*](#nt:template-parameter "13.2 Template 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.2 Template parameters [temp.param]") unless that template parameter is deducible from the
|
||||
parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the function template or
|
||||
has a default argument ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction"))[.](#19.sentence-3)
|
||||
|
||||
A template parameter of a deduction guide template ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3 Deduction 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.1 Preamble [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.2 Template parameters [temp.param]") of
|
||||
a template [*template-parameter*](#nt:template-parameter "13.2 Template 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.2 Template parameters [temp.param]") in the scope of the template [*template-parameter*](#nt:template-parameter "13.2 Template 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.4 Concept-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
131
cppdraft/temp/point.md
Normal 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.5 Exception 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.5 Exception 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.5 Exception 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.5 Exception specifications [except.spec]") immediately follows the namespace
|
||||
scope declaration or definition that requires the[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception 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.1 Preamble [dcl.pre]") of the[*translation-unit*](basic.link#nt:translation-unit "6.7 Program and linkage [basic.link]"),
|
||||
prior to the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5 Private module fragment [module.private.frag]") (if any),
|
||||
the point after the [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]") of the [*translation-unit*](basic.link#nt:translation-unit "6.7 Program 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.5 Private 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.3 One-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.4 Compound statement or block [stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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
241
cppdraft/temp/pre.md
Normal 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.1 Preamble [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.1 Preamble [temp.pre]")
|
||||
[*template-head*](#nt:template-head "13.1 Preamble [temp.pre]") [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")
|
||||
[*template-head*](#nt:template-head "13.1 Preamble [temp.pre]") [*concept-definition*](temp.concept#nt:concept-definition "13.7.9 Concept definitions [temp.concept]")
|
||||
|
||||
[template-head:](#nt:template-head "13.1 Preamble [temp.pre]")
|
||||
template < [*template-parameter-list*](#nt:template-parameter-list "13.1 Preamble [temp.pre]") > [*requires-clause*](#nt:requires-clause "13.1 Preamble [temp.pre]")opt
|
||||
|
||||
[template-parameter-list:](#nt:template-parameter-list "13.1 Preamble [temp.pre]")
|
||||
[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")
|
||||
[*template-parameter-list*](#nt:template-parameter-list "13.1 Preamble [temp.pre]") , [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")
|
||||
|
||||
[requires-clause:](#nt:requires-clause "13.1 Preamble [temp.pre]")
|
||||
requires [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]")
|
||||
|
||||
[constraint-logical-or-expression:](#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]")
|
||||
[*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1 Preamble [temp.pre]")
|
||||
[*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]") || [*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1 Preamble [temp.pre]")
|
||||
|
||||
[constraint-logical-and-expression:](#nt:constraint-logical-and-expression "13.1 Preamble [temp.pre]")
|
||||
[*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1 Grammar [expr.prim.grammar]")
|
||||
[*constraint-logical-and-expression*](#nt:constraint-logical-and-expression "13.1 Preamble [temp.pre]") && [*primary-expression*](expr.prim.grammar#nt:primary-expression "7.5.1 Grammar [expr.prim.grammar]")
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The > token following the[*template-parameter-list*](#nt:template-parameter-list "13.1 Preamble [temp.pre]") of a[*template-declaration*](#nt:template-declaration "13.1 Preamble [temp.pre]") can be the product of replacing a>> token by two consecutive > tokens ([[temp.names]](temp.names "13.3 Names 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.1 Preamble [dcl.pre]") in a [*template-declaration*](#nt:template-declaration "13.1 Preamble [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.1 General [class.mem.general]"), or
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
be a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]"), or
|
||||
|
||||
- [(2.6)](#2.6)
|
||||
|
||||
be an [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [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.1 Preamble [temp.pre]") is a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]")[.](#3.sentence-1)
|
||||
|
||||
A declaration introduced by a template declaration of avariable is a [*variable template*](#def:template,variable "13.1 Preamble [temp.pre]")[.](#3.sentence-2)
|
||||
|
||||
A variable template at class scope is a[*static data member template*](#def:template,static_data_member "13.1 Preamble [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.1 Preamble [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.1 Preamble [dcl.pre]") shall not be an[*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")[.](#4.sentence-2)
|
||||
|
||||
In a function template declaration, the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.3 Names of template specializations [temp.names]") declares a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial 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.1 Preamble [temp.pre]"),
|
||||
explicit specialization, or explicit instantiation, the[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [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.4 Explicit 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.7 Template declarations")) and must obey the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.1 General")), except
|
||||
that a function template can share a name with [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]")*s*,
|
||||
a type, non-template functions ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) and/or function templates ([[temp.over]](temp.over "13.10.4 Overload resolution"))[.](#7.sentence-1)
|
||||
|
||||
Specializations, including partial specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial 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.1 Preamble [temp.pre]") if it is
|
||||
|
||||
- [(8.1)](#8.1)
|
||||
|
||||
a template,
|
||||
|
||||
- [(8.2)](#8.2)
|
||||
|
||||
an entity defined ([[basic.def]](basic.def "6.2 Declarations and definitions")) or created ([[class.temporary]](class.temporary "6.8.7 Temporary objects"))
|
||||
within the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") of an expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure 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.1 Preamble [temp.pre]") is
|
||||
a function template or a function that is templated[.](#8.sentence-3)
|
||||
|
||||
A [*templated class*](#def:class,templated "13.1 Preamble [temp.pre]") is
|
||||
a class template or a class that is templated[.](#8.sentence-4)
|
||||
|
||||
A [*templated variable*](#def:variable,templated "13.1 Preamble [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.1 Preamble [temp.pre]") is written
|
||||
in terms of its template parameters[.](#9.sentence-1)
|
||||
|
||||
The optional [*requires-clause*](#nt:requires-clause "13.1 Preamble [temp.pre]") following a[*template-parameter-list*](#nt:template-parameter-list "13.1 Preamble [temp.pre]") allows the specification of
|
||||
constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations")) on template arguments ([[temp.arg]](temp.arg "13.4 Template arguments"))[.](#9.sentence-2)
|
||||
|
||||
The [*requires-clause*](#nt:requires-clause "13.1 Preamble [temp.pre]") introduces the[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") that results from interpreting
|
||||
the [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]") as a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")[.](#9.sentence-3)
|
||||
|
||||
The [*constraint-logical-or-expression*](#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]") of a[*requires-clause*](#nt:requires-clause "13.1 Preamble [temp.pre]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context dependence"))[.](#9.sentence-4)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
The expression in a [*requires-clause*](#nt:requires-clause "13.1 Preamble [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.1 Preamble [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.3 One-definition rule"))
|
||||
in which it is implicitly instantiated ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation")) unless the
|
||||
corresponding specialization is explicitly instantiated ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation"))
|
||||
in some translation unit; no diagnostic is required[.](#10.sentence-1)
|
||||
1481
cppdraft/temp/res.md
Normal file
1481
cppdraft/temp/res.md
Normal file
File diff suppressed because it is too large
Load Diff
343
cppdraft/temp/res/general.md
Normal file
343
cppdraft/temp/res/general.md
Normal 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.3 Dependent 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.3 Type-dependent expressions"), [[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4 Value-dependent expressions"))[.](#1.sentence-4)
|
||||
|
||||
A [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is never dependent in a specialization and
|
||||
is therefore replaced during lookup for that specialization ([[basic.lookup]](basic.lookup "6.5 Name 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.3 Conversion 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.1 Point 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.1 General [temp.res.general]")
|
||||
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
typename [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.1 General [temp.res.general]") are
|
||||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and
|
||||
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") (if any)[.](#3.sentence-1)
|
||||
|
||||
A [*typename-specifier*](#nt:typename-specifier "13.8.1 General [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.3 Simple type specifiers [dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple 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.5 Qualified 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.1 General [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.1 General [temp.res.general]"),[*type-requirement*](expr.prim.req.type#nt:type-requirement "7.5.8.3 Type requirements [expr.prim.req.type]"),[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"),[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]"),[*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The using enum declaration [enum.udecl]"),
|
||||
or
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
a [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") of a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [class.mem.general]"), or
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") of a
|
||||
* [(4.3.1)](#4.3.1)
|
||||
|
||||
[*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]"),
|
||||
|
||||
* [(4.3.2)](#4.3.2)
|
||||
|
||||
[*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]"),
|
||||
|
||||
* [(4.3.3)](#4.3.3)
|
||||
|
||||
[*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]"),
|
||||
|
||||
* [(4.3.4)](#4.3.4)
|
||||
|
||||
[*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]"),
|
||||
|
||||
* [(4.3.5)](#4.3.5)
|
||||
|
||||
default argument of a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]"), or
|
||||
|
||||
* [(4.3.6)](#4.3.6)
|
||||
|
||||
[*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a
|
||||
* [(4.4.1)](#4.4.1)
|
||||
|
||||
[*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [dcl.pre]") or [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") in namespace scope,
|
||||
|
||||
* [(4.4.2)](#4.4.2)
|
||||
|
||||
[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),
|
||||
|
||||
* [(4.4.3)](#4.4.3)
|
||||
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),[116](#footnote-116 "This includes friend function declarations.") unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,
|
||||
|
||||
* [(4.4.4)](#4.4.4)
|
||||
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") of a function or function template declaration
|
||||
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is qualified,
|
||||
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument,
|
||||
|
||||
* [(4.4.5)](#4.4.5)
|
||||
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") in a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or [*requirement-parameter-list*](expr.prim.req.general#nt:requirement-parameter-list "7.5.8.1 General [expr.prim.req.general]"),
|
||||
unless that [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") appears in a default argument, or
|
||||
|
||||
* [(4.4.6)](#4.4.6)
|
||||
|
||||
[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") (which necessarily declares a constant template parameter)[.](#4.sentence-1)
|
||||
|
||||
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") ([[basic.splice]](basic.splice "6.6 Splice 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.2 Type names [dcl.name]")using Alias = [:^^int:]; // OK, in a [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type 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.2 Type 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.1 General [dcl.decl.general]")auto h() -> [:^^S:]<T*>; // OK, [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")using enum [:^^Enum:]; // OK, [*using-enum-declarator*](enum.udecl#nt:using-enum-declarator "9.8.2 The 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.3 Qualified 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.10 The using declaration [namespace.udecl]") whose terminal name is dependent
|
||||
is interpreted as a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") if the [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The 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.1 Preamble [dcl.pre]")s that fail ([[dcl.pre]](dcl.pre "9.1 Preamble")),
|
||||
can be generated for a templated entity
|
||||
or a substatement of a constexpr if statement ([[stmt.if]](stmt.if "8.5.2 The 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.1 Preamble [dcl.pre]")s that fail,
|
||||
can be generated for the [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound 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.1 Preamble [dcl.pre]")s that fail,
|
||||
can be generated for a default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") and
|
||||
the default [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.8 Alias 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.3 Constrained 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.1 Preamble [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.10 The 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.10 The 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.7 Constant 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.3 Names 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.5 Exception specifications [except.spec]")*s* of function templates and default
|
||||
arguments and [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")*s* of
|
||||
member functions of class templates are considered definitions ([[temp.decls]](temp.decls "13.7 Template 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
1136
cppdraft/temp/spec.md
Normal file
File diff suppressed because it is too large
Load Diff
145
cppdraft/temp/spec/general.md
Normal file
145
cppdraft/temp/spec/general.md
Normal 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.1 General [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.3 Names 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.3 Names 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.2 Implicit instantiation")) for a given argument list or be explicitly
|
||||
instantiated ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation"))[.](#4.sentence-1)
|
||||
|
||||
A [*specialization*](#def:specialization "13.9.1 General [temp.spec.general]") is a class, variable, function, or class member that is either
|
||||
instantiated ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation")) from a templated entity or is an
|
||||
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) of a templated entity[.](#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.3 Names 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.3 One-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.1 General [class.derived.general]"), [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]"), [*enumerator-list*](dcl.enum#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]"),
|
||||
or static data member or variable template initializer[.](#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.2 Dependent 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*]
|
||||
345
cppdraft/temp/spec/partial.md
Normal file
345
cppdraft/temp/spec/partial.md
Normal 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.2 Matching 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.1 Preamble [temp.pre]")*s* and template argument lists ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.5 Template 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.5 Partial 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.3 Names 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.4 Meaning of declarators"), [[class.mem]](class.mem "11.4 Class members"), [[temp.mem]](temp.mem "13.7.3 Member 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.10 The 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.10 The 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.3 Partial 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.4 Variadic 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.3 Names 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.3 Partial 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.3 Template 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.3 Constrained 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.1 Preamble [temp.pre]") and the [*template-id*](temp.names#nt:template-id "13.3 Names 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.5 Deducing 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.3 Partial 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.3 Constrained 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.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.2 Implicit instantiation"), [[temp.explicit]](temp.explicit "13.9.3 Explicit 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*]
|
||||
167
cppdraft/temp/spec/partial/general.md
Normal file
167
cppdraft/temp/spec/partial/general.md
Normal 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.2 Matching 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.1 Preamble [temp.pre]")*s* and template argument lists ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.5 Template 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.5 Partial 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.3 Names 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.4 Meaning of declarators"), [[class.mem]](class.mem "11.4 Class members"), [[temp.mem]](temp.mem "13.7.3 Member 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.10 The 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.10 The 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.3 Partial 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.4 Variadic 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.3 Names 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)
|
||||
80
cppdraft/temp/spec/partial/match.md
Normal file
80
cppdraft/temp/spec/partial/match.md
Normal 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.3 Partial 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.3 Template 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.3 Constrained 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.1 Preamble [temp.pre]") and the [*template-id*](temp.names#nt:template-id "13.3 Names 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)
|
||||
59
cppdraft/temp/spec/partial/member.md
Normal file
59
cppdraft/temp/spec/partial/member.md
Normal 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.2 Implicit instantiation"), [[temp.explicit]](temp.explicit "13.9.3 Explicit 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*]
|
||||
60
cppdraft/temp/spec/partial/order.md
Normal file
60
cppdraft/temp/spec/partial/order.md
Normal 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.5 Deducing 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.3 Partial 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.3 Constrained 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.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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
32
cppdraft/temp/static.md
Normal 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
156
cppdraft/temp/type.md
Normal 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.3 Names of template specializations [temp.names]")*s* are the same if
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
their [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")*s*,[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")*s*, or[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6 User-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.3 Names 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.3 Constant template arguments"))
|
||||
are template-argument-equivalent (see below), and
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
their corresponding template [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* refer to the same template[.](#1.sentence-1)
|
||||
|
||||
Two [*template-id*](temp.names#nt:template-id "13.3 Names 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.6 Type 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.10 Equality 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.2 Closure 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.3 Type-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.6 Decltype specifiers [dcl.type.decltype]")*s* refer to the same type only if their [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")*s* are
|
||||
equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function 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.4 The 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.7 Constant 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.7 Constant expressions [expr.const]") of a [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack 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.4 Pack indexing specifier [dcl.type.pack.index]")*s* refer to the same type
|
||||
only if their [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")*s* are equivalent ([[temp.over.link]](temp.over.link "13.7.7.2 Function template overloading"))[.](#6.sentence-1)
|
||||
|
||||
Otherwise, two such [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack 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.2 Template parameters [temp.param]") decays to a pointer[.](#footnote-113.sentence-1)
|
||||
370
cppdraft/temp/variadic.md
Normal file
370
cppdraft/temp/variadic.md
Normal 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.4 Variadic 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.4 Variadic 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.4 Variadic templates [temp.variadic]")*[*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") pack* is a lambda capture that introduces an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") for each of the elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.3 Captures [expr.prim.lambda.capture]") pack};} foo(); // xs contains zero [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]")*s* foo(1); // xs contains one [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [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.4 Variadic templates [temp.variadic]") is an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") that introduces zero or more structured bindings ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured 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.4 Variadic 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.3 Captures [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.3 Captures [expr.prim.lambda.capture]") pack
|
||||
is the number of elements in the pack expansion of its [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.4 Variadic templates [temp.variadic]") consists of a [*pattern*](#def:pack_expansion,pattern "13.7.4 Variadic 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.6 Functions")); the pattern is the[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") without the ellipsis[.](#6.1.sentence-1)
|
||||
|
||||
- [(6.2)](#6.2)
|
||||
|
||||
In a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"));
|
||||
the pattern is a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The 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.1 General [class.mem.general]") ([[class.mem.general]](class.mem.general "11.4.1 General"));
|
||||
the pattern is a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [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.2 Template parameters")):
|
||||
* [(6.4.1)](#6.4.1)
|
||||
|
||||
if the template parameter pack is a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]");
|
||||
the pattern is the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [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.2 Template parameters [temp.param]");
|
||||
the pattern is the corresponding [*type-parameter*](temp.param#nt:type-parameter "13.2 Template 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.2 Template parameters [temp.param]"),[*variable-tt-parameter*](temp.param#nt:variable-tt-parameter "13.2 Template parameters [temp.param]"), or[*concept-tt-parameter*](temp.param#nt:concept-tt-parameter "13.2 Template 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.1 General [dcl.init.general]") ([[dcl.init]](dcl.init "9.5 Initializers"));
|
||||
the pattern is an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [class.derived.general]") ([[class.derived]](class.derived "11.7 Derived classes"));
|
||||
the pattern is a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")) for a[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") whose [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") denotes a
|
||||
base class; the pattern is the [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing 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.3 Names of template specializations [temp.names]") ([[temp.arg]](temp.arg "13.4 Template arguments"));
|
||||
the pattern is a [*template-argument*](temp.names#nt:template-argument "13.3 Names 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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"));
|
||||
the pattern is an [*attribute*](dcl.attr.grammar#nt:attribute "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute syntax and semantics"));
|
||||
the pattern is an [*annotation*](dcl.attr.grammar#nt:annotation "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2 Alignment specifier")); the pattern is
|
||||
the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute 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.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")); the pattern is
|
||||
the [*capture*](expr.prim.lambda.capture#nt:capture "7.5.6.3 Captures [expr.prim.lambda.capture]") without the ellipsis[.](#6.12.sentence-1)
|
||||
|
||||
- [(6.13)](#6.13)
|
||||
|
||||
In a [sizeof... expression](expr.sizeof "7.6.2.5 Sizeof [expr.sizeof]"); the pattern is an[*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.4 Pack indexing expression [expr.prim.pack.index]");
|
||||
the pattern is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.4 Pack indexing specifier [dcl.type.pack.index]");
|
||||
the pattern is a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")[.](#6.15.sentence-1)
|
||||
|
||||
- [(6.16)](#6.16)
|
||||
|
||||
In a [*fold-expression*](expr.prim.fold#nt:fold-expression "7.5.7 Fold expressions [expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold expressions"));
|
||||
the pattern is the [*cast-expression*](expr.cast#nt:cast-expression "7.6.3 Explicit 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.5 Fold 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.4 Variadic 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.4 The 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.1 General [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.3 Names 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.1 General [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.3 Captures [expr.prim.lambda.capture]") pack,
|
||||
the element is an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") designating the variable introduced by
|
||||
the ith [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") that resulted from instantiation of
|
||||
the [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [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.1 General [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.5 Sizeof")) 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.4 Pack 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.1 General [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.4 Pack 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.4 The 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.1 Attribute 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.7 Fold expressions [expr.prim.fold]") ([[expr.prim.fold]](expr.prim.fold "7.5.7 Fold 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.7 Fold 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.3 Explicit 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.5 Fold 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.1 General [expr.post.general]"),[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]"),[*template-argument-list*](temp.names#nt:template-argument-list "13.3 Names 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*]
|
||||
Reference in New Issue
Block a user