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

259 lines
17 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.9Template instantiation and specialization[temp.spec]") can be referred to by a[*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]"):
[simple-template-id:](#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[template-id:](#nt:template-id "13.3Names of template specializations[temp.names]")
[*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1General[over.oper.general]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[*literal-operator-id*](over.literal#nt:literal-operator-id "12.6User-defined literals[over.literal]") < [*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]")opt >
[template-name:](#nt:template-name "13.3Names of template specializations[temp.names]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[template-argument-list:](#nt:template-argument-list "13.3Names of template specializations[temp.names]")
[*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") ...opt
[*template-argument-list*](#nt:template-argument-list "13.3Names of template specializations[temp.names]") , [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") ...opt
[template-argument:](#nt:template-argument "13.3Names of template specializations[temp.names]")
[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*template-name*](#nt:template-name "13.3Names 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.3Names of template specializations[temp.names]"),[*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]"), or[*template-name*](#nt:template-name "13.3Names 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.3Names of template specializations[temp.names]") if either
- [(3.1)](#3.1)
it follows a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice 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.3Conversion 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.3Qualified 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.10The using declaration[namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10The using declaration")),
in a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") ([[dcl.meaning]](dcl.meaning "9.3.4Meaning 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.3Qualified names[expr.prim.id.qual]") ([[temp.res]](temp.res "13.8Name resolution"))[.](#3.sentence-1)
[*Note [1](#note-1)*:
If the name is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"),
it is then interpreted as a [*template-name*](#nt:template-name "13.3Names 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.2Dependent 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.3Names 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.3Names of template specializations[temp.names]") and completes
the [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice 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.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice 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.3Qualified names[expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified 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.7Constant expressions[expr.const]") of a [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") shall not be an unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression 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.9Expression 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.9template 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.3Names 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.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") is [*valid*](#def:template-id,valid "13.3Names 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.4Variadic 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.3Names of template specializations[temp.names]"),
- [(8.3)](#8.3)
each [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]") matches the corresponding
template parameter ([[temp.arg]](temp.arg "13.4Template 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.3Names of template specializations[temp.names]") or [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice 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.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall be valid unless its respective[*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") names or designates a function template ([[temp.deduct]](temp.deduct "13.10.3Template 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.3Names of template specializations[temp.names]") of a [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") or
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of a [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") designates a constrained non-function template
or
a constrained template template parameter,
and
all [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]")*s* in the [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") are non-dependent ([[temp.dep.temp]](temp.dep.temp "13.8.3.7Dependent template arguments")),
the associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
of the constrained template
shall be satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints"))[.](#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.3Names of template specializations[temp.names]") is a [*simple-template-id*](#nt:simple-template-id "13.3Names of template specializations[temp.names]") where the [*template-name*](#nt:template-name "13.3Names of template specializations[temp.names]") is a [*concept-name*](temp.concept#nt:concept-name "13.7.9Concept 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.3Constrained declarations[temp.constr.decl]") ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))
is satisfied ([[temp.constr.constr]](temp.constr.constr "13.5.2Constraints")) 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.3Constrained declarations[temp.constr.decl]") is an unevaluated operand,
a concept-id appearing in a [*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained 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.2Type names[dcl.name]") of a dynamic_cast, static_cast, reinterpret_cast or const_cast, or which encloses the [*template-argument*](#nt:template-argument "13.3Names of template specializations[temp.names]")*s* of a subsequent [*template-id*](#nt:template-id "13.3Names of template specializations[temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
is considered nested for the purpose of this description[.](#footnote-108.sentence-1)