259 lines
17 KiB
Markdown
259 lines
17 KiB
Markdown
[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)
|