[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
- 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 correspondingtemplate-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
:
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
]