[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 X* alloc(); template 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](#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 class X { /* ... */ }; X< 1>2 > x1; // syntax error X<(1>2)> x2; // OKtemplate class Y { /* ... */ }; Y> x3; // OK, same as Y > x3; Y>1>> x4; // syntax error Y>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 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 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*](#nt:template-id "13.3 Names of template specializations [temp.names]")}template struct B {template struct C { };}; // deprecated: T​::​C is assumed to name a class template:template class TT = T::template C> struct D { }; D > 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 X;struct S {using type = int;};using T1 = X; // 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](#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 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 class X>struct S4 { X x; // ill-formed, no diagnostic required}; template concept C2 = sizeof(T) == 1; template struct S { }; template struct S; // error: constraints not satisfiedtemplate<> struct S { }; // 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 concept C = true;static_assert(C); // 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)