[temp.names] (original) (raw)
13 Templates [temp]
13.3 Names of template specializations [temp.names]
The component name of asimple-template-id,template-id, ortemplate-nameis the first name in it.
[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<class T> void f(T* p) { T* p1 = p->alloc<200>(); T* p2 = p->template alloc<200>(); T::adjust<100>(); T::template adjust<100>(); } — _end example_]
When parsing a template-argument-list, the first non-nested>108is 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.
[Note 2:
The second >token produced by this replacement rule can terminate an enclosingtemplate-id construct or it can be part of a different construct (e.g., a cast).
— _end note_]
[Example 2: template<int i> class X { }; X< 1>2 > x1; X<(1>2)> x2; template<class T> class Y { }; Y<X<1>> x3; Y<X<6>>1>> x4; Y<X<(6>>1)>> x5; — _end example_]
A name prefixed by the keywordtemplateshall be followed by a template argument list or refer to a class template or an alias template.
The keyword template shall not appear immediately before a ~ token (as to name a destructor).
[Note 3:
The keywordtemplatecannot be applied to non-template members of class templates.
— _end note_]
[Note 4:
As is the case with thetypenameprefix, thetemplateprefix is well-formed even when lookup for the name would already find a template.
— _end note_]
[Example 3: 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); a.template f(t); } template <class T> struct B { template <class T2> struct C { };};template <class T, template <class X> class TT = T::template C> struct D { }; D<B<int> > db; — _end example_]
A template-id 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 is non-dependent, the associated constraints are satisfied as specified in the next paragraph.
A simple-template-id shall be valid unless it names a function template specialization ([temp.deduct]).
[Example 4: template<class T, T::type n = 0> class X;struct S { using type = int;};using T1 = X<S, int, int>; using T2 = X<>; using T3 = X<1>; using T4 = X<int>; using T5 = X<S>; — _end example_]
When the template-nameof a simple-template-idnames a constrained non-function template or a constrained template template parameter, and all template-argument_s_in the simple-template-idare non-dependent ([temp.dep.temp]), the associated constraints ([temp.constr.decl]) of the constrained template shall be satisfied ([temp.constr.constr]).
[Example 5: template<typename T> concept C1 = sizeof(T) != sizeof(int);template<C1 T> struct S1 { };template<C1 T> using Ptr = T*; S1<int>* p; Ptr<int> p; template<typename T> struct S2 { Ptr<int> x; }; template<typename T> struct S3 { Ptr<T> x; }; S3<int> x; template<template<C1 T> class X> struct S4 { X<int> x; };template<typename T> concept C2 = sizeof(T) == 1;template<C2 T> struct S { };template struct S<char[2]>; template<> struct S<char[2]> { }; — _end example_]
A concept-id is a prvalue of type bool, and does not name a template specialization.
[Note 5:
Since a constraint-expression is an unevaluated operand, a concept-id appearing in a constraint-expressionis not evaluated except as necessary to determine whether the normalized constraints are satisfied.
— _end note_]
[Example 6: template<typename T> concept C = true;static_assert(C<int>); — _end example_]