[temp.names] (original) (raw)

13 Templates [temp]

13.3 Names of template specializations [temp.names]

For atemplate-nameto be explicitly qualified by the template arguments, the name must be considered to refer to a template.

[ Note

:

Whether a name actually refers to a template cannot be known in some cases until after argument dependent lookup is done ([basic.lookup.argdep]).

end note

]

A name is considered to refer to a template if name lookup finds a template-nameor an overload set that contains a function template.

A name is also considered to refer to a template if it is an unqualified-idfollowed by a <and name lookup either finds one or more functions or finds nothing.

When a name is considered to be atemplate-name, and it is followed by a <, the <is always taken as the delimiter of atemplate-argument-listand never as the less-than operator.

When parsing a template-argument-list, the first non-nested>128is 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

:

The second >token produced by this replacement rule may terminate an enclosingtemplate-id construct or it may be part of a different construct (e.g., a cast).

end note

]

[ Example

:

template class X { };

X< 1>2 > x1;
X<(1>2)> x2;

template class Y { }; Y<X<1>> x3;
Y<X<6>>1>> x4;
Y<X<(6>>1)>> x5;

end example

]

In these contexts, a < token is always assumed to introduce atemplate-argument-list.

In all other contexts, when naming a template specialization of a member of an unknown specialization ([temp.dep.type]), the member template name shall be prefixed by the keyword template.

[ Example

:

struct X { templatestd::size_t X* alloc(); templatestd::size_t static X* adjust(); }; template void f(T* p) { T* p1 = p->alloc<200>();
T* p2 = p->template alloc<200>();
T::adjust<100>();
T::template adjust<100>();
}

end example

]

A name prefixed by the keywordtemplateshall be a template-id or the name shall refer to a class template or an alias template.

[ Note

:

The keywordtemplatemay not be applied to non-template members of class templates.

end note

]

[ Note

:

As is the case with thetypenameprefix, thetemplateprefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the->or.is not dependent on atemplate-parameter, or the use does not appear in the scope of a template.

end note

]

[ Example

:

template struct A { void f(int); template void f(U); };

template void f(T t) { A a; a.template f<>(t);
a.template f(t);
}

template struct B { template struct C { }; };

template <class T, template class TT = T::template C> struct D { }; D<B > 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

:

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;
using T5 = X;

end example

]

When the template-nameof a simple-template-idnames a constrained non-function template or a constrained template template-parameter, but not a member template that is a member of an unknown specialization ([temp.res]), and all template-argumentsin 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

:

template concept C1 = sizeof(T) != sizeof(int);

template struct S1 { }; template using Ptr = T*;

S1* p;
Ptr p;

template struct S2 { Ptr x; };

template struct S3 { Ptr x; };

S3 x;

template<template class X> struct S4 { X x;
};

template concept C2 = sizeof(T) == 1;

template 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.

A concept-id evaluates to trueif the concept's normalized constraint-expressionis satisfied ([temp.constr.constr]) by the specified template arguments andfalse otherwise.

[ Note

:

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

:

template concept C = true; static_assert(C);

end example

]