Init
This commit is contained in:
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)
|
||||
Reference in New Issue
Block a user