A template specialization can be referred to by a template-id:
simple-template-id: template-name < template-argument-listopt >
template-id: simple-template-id operator-function-id < template-argument-listopt > literal-operator-id < template-argument-listopt >
template-name: identifier
template-argument-list: template-argument ...opt template-argument-list , template-argument ...opt
template-argument: constant-expression type-id id-expression
[ Note: The name lookup rules are used to associate the use of a name with a template declaration; that is, to identify a name as a template-name. — end note ]
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.
After name lookup finds that a name is a template-name or that an operator-function-id or a literal-operator-id refers to a set of overloaded functions any member of which is a function template, if this is followed by a <, the < is always taken as the delimiter of a template-argument-list and never as the less-than operator. When parsing a template-argument-list, the first non-nested >136 is 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 enclosing template-id construct or it may be part of a different construct (e.g. a cast). — end note ] [ Example:
template<int i> class X { /* ... */ }; X< 1>2 > x1; // syntax error X<(1>2)> x2; // OK template<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 ]
The keyword template is said to appear at the top level in a qualified-id if it appears outside of a template-argument-list or decltype-specifier. In a qualified-id of a declarator-id or in a qualified-id formed by a class-head-name or enum-head-name, the keyword template shall not appear at the top level. In a qualified-id used as the name in a typename-specifier, elaborated-type-specifier, using-declaration, or class-or-decltype, an optional keyword template appearing at the top level is ignored. In these contexts, a < token is always assumed to introduce a template-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 { 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>(); // ill-formed: < means less than T* p2 = p->template alloc<200>(); // OK: < starts template argument list T::adjust<100>(); // ill-formed: < means less than T::template adjust<100>(); // OK: < starts template argument list }
— end example ]
A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template or an alias template. [ Note: The keyword template may not be applied to non-template members of class templates. — end note ] [ Note: As is the case with the typename prefix, the template prefix 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 a template-parameter, or the use does not appear in the scope of a template. — end note ] [ Example:
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 } template <class T> struct B { template <class T2> struct C { }; }; // OK: T::template C names a class template: template <class T, template <class X> class TT = T::template C> struct D { }; D<B<int> > db;
— end example ]
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, is considered nested for the purpose of this description.