[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)
