Files
cppdraft_translate/cppdraft/temp/names.md
2025-10-25 03:02:53 +03:00

17 KiB
Raw Blame History

[temp.names]

13 Templates [temp]

13.3 Names of template specializations [temp.names]

1

#

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-name:
identifier

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

2

#

The component name of asimple-template-id,template-id, ortemplate-name is the first name in it.

3

#

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]

4

#

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]

5

#

The keyword template shall not appear immediately after a declarative nested-name-specifier ([expr.prim.id.qual]).

6

#

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]

7

#

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]

8

#

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]

9

#

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]

10

#

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]

108)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 orsplice-specialization-specifier, is considered nested for the purpose of this description.