17 KiB
[temp.names]
13 Templates [temp]
13.3 Names of template specializations [temp.names]
A template specialization can be referred to by atemplate-id:
simple-template-id:
template-name < template-argument-listopt >
template-id:
simple-template-id
operator-function-id < template-argument-listopt >
literal-operator-id < template-argument-listopt >
template-argument-list:
template-argument ...opt
template-argument-list , template-argument ...opt
template-argument:
constant-expression
type-id
nested-name-specifieropt template-name
nested-name-specifier template template-name
The component name of asimple-template-id,template-id, ortemplate-name is the first name in it.
A < is interpreted as the delimiter of a template-argument-list if either
it follows a splice-specifier that either
appears in a type-only context or
is preceded by template or typename, or
it follows a name that is not a conversion-function-id and
that follows the keyword template or a ~ after a nested-name-specifier or in a class member access expression, or
for which name lookup finds the injected-class-name of a class template or finds any declaration of a template, or
that is an unqualified name for which name lookup either finds one or more functions or finds nothing, or
that is a terminal name in a using-declarator ([namespace.udecl]), in a declarator-id ([dcl.meaning]), or in a type-only context other than a nested-name-specifier ([temp.res]).
[Note 1:
If the name is an identifier, it is then interpreted as a template-name.
The keyword template is used to indicate that a dependent qualified name ([temp.dep.type]) denotes a template where an expression might appear.
â end note]
[Example 1: struct X {templatestd::size_t X* alloc(); templatestd::size_t static X* adjust();};template 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]
When parsing a template-argument-list, the first non-nested>108 is taken as the ending delimiter rather than a greater-than operator.
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 and completes the template-id or splice-specialization-specifier.
[Note 2:
The second > token produced by this replacement rule can terminate an enclosingtemplate-id or splice-specialization-specifier construct or it can be part of a different construct (e.g., a cast).
â end note]
[Example 2: template class X { /* ... */ };
X< 1>2 > x1; // syntax error X<(1>2)> x2; // OKtemplate 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]
The keyword template shall not appear immediately after a declarative nested-name-specifier ([expr.prim.id.qual]).
The constant-expression of a template-argument shall not be an unparenthesized splice-expression.
[Example 3: template struct S { };constexpr int k = 5;constexpr std::meta::info r = ^^k; S<[:r:]> s1; // error: unparenthesized splice-expression used as template argument S<([:r:])> s2; // OK S<[:r:] + 1> s3; // OK â end example]
A name prefixed by the keywordtemplate shall be followed by a template argument list or refer to a class template or an alias template.
The latter case is deprecated ([depr.template.template]).
The keyword template shall not appear immediately before a ~ token (as to name a destructor).
[Note 3:
The keywordtemplate cannot be applied to non-template members of class templates.
â end note]
[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.
â end note]
[Example 4: template struct A {void f(int); template void f(U);};
template void f(T t) { A a; a.template f<>(t); // OK, calls template a.template f(t); // error: not a template-id}template struct B {template struct C { };};
// deprecated: T::C is assumed to name a class template:template <class T, template class TT = T::template C> struct D { }; D<B > db; â end example]
A template-id or splice-specialization-specifier is valid if
there are at most as many arguments as there are parameters or a parameter is a template parameter pack ([temp.variadic]),
there is an argument for each non-deducible non-pack parameter that does not have a default template-argument,
each template-argument matches the corresponding template parameter ([temp.arg]),
substitution of each template argument into the following template parameters (if any) succeeds, and
if the template-id or splice-specialization-specifier is non-dependent, the associated constraints are satisfied as specified in the next paragraph.
A simple-template-id orsplice-specialization-specifier shall be valid unless its respectivetemplate-name or splice-specifier names or designates a function template ([temp.deduct]).
[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; // error: substitution failure for second template parameterusing T5 = X; // OK â end example]
When the template-name of a simple-template-id or the splice-specifier of a splice-specialization-specifier designates a constrained non-function template or a constrained template template parameter, and all template-arguments in the simple-template-id orsplice-specialization-specifier are non-dependent ([temp.dep.temp]), the associated constraints ([temp.constr.decl]) of the constrained template shall be satisfied ([temp.constr.constr]).
[Example 6: template concept C1 = sizeof(T) != sizeof(int);
template struct S1 { };template using Ptr = T*;
S1* p; // error: constraints not satisfied Ptr p; // error: constraints not satisfiedtemplatestruct S2 { Ptr x; }; // ill-formed, no diagnostic requiredtemplatestruct S3 { Ptr x; }; // OK, satisfaction is not required S3 x; // error: constraints not satisfiedtemplate<template class X>struct S4 { X x; // ill-formed, no diagnostic required};
template concept C2 = sizeof(T) == 1;
template struct S { };
template struct S<char[2]>; // error: constraints not satisfiedtemplate<> struct S<char[2]> { }; // error: constraints not satisfied â end example]
A concept-id is a simple-template-id where the template-name is a concept-name.
A concept-id is a prvalue of type bool, and does not name a template specialization.
A concept-id evaluates to true if the concept's normalized constraint-expression ([temp.constr.decl]) is satisfied ([temp.constr.constr]) by the specified template arguments andfalse otherwise.
[Note 5:
Since a constraint-expression is an unevaluated operand, a concept-id appearing in a constraint-expression is not evaluated except as necessary to determine whether the normalized constraints are satisfied.
â end note]
[Example 7: template concept C = true;static_assert(C); // OK â end example]
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 orsplice-specialization-specifier, is considered nested for the purpose of this description.