[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

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_]