A template specialization может обозначаться как 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: Эти name lookup правила используются , чтобы связать использование имени с декларацией шаблона; то есть, чтобы идентифицировать имя как template-name. ] — end note
Чтобы a template-name было явно квалифицировано аргументами шаблона, необходимо, чтобы имя ссылалось на шаблон.
После того, как name lookup обнаруживается, что имя является a template-name или что a operator-function-idили a literal-operator-idотносится к набору перегруженных функций, любой член которых является шаблоном функции, если за ним следует a <, < всегда используется как разделитель a template-argument-list и никогда как менее- чем оператор. При синтаксическом анализе template-argument-listпервый невложенный >136 используется как конечный разделитель, а не как оператор «больше». Точно так же первый невложенный токен >> рассматривается как два последовательных, но различных > токена, первый из которых считается концом template-argument-listи завершает template-id. [ Note: Второй > токен, созданный этим правилом замены, может завершать включающую template-idконструкцию или может быть частью другой конструкции (например, приведение). ] [ — 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 ]
template Говорят, что ключевое слово появляется на верхнем уровне в, qualified-id если оно появляется за пределами template-argument-listили decltype-specifier. В a qualified-idиз a declarator-idили в a, qualified-idобразованном символом class-head-nameили enum-head-name, ключевое слово template не должно появляться на верхнем уровне. В qualified-idкачестве имени в typename-specifier, elaborated-type-specifier, using-declaration, или class-or-decltype, необязательный ключевое слово template появляется на уровне верхней игнорируется. В этих контекстах < всегда предполагается , что токен представляет template-argument-list. Во всех других контекстах при именовании специализации шаблона элемента неизвестной специализации ([temp.dep.type]) имя шаблона элемента должно начинаться с префикса ключевого слова 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 ]
Имя с префиксом ключевого слова template должно быть template-idили имя должно относиться к шаблону класса или шаблону псевдонима. [ Note: Ключевое слово template не может применяться к членам, не являющимся шаблонами, шаблонов классов. ] [ Как и в случае с префиксом, префикс разрешен в случаях, когда это не является строго необходимым; то есть, когда или выражение слева от или не зависит от , или использование не появляется в области действия шаблона. ] [ — end note Note: typenametemplatenested-name-specifier->.template-parameter — 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 ]
> , Покрывающие type-id из dynamic_cast, static_cast, reinterpret_cast или const_cast, или, вмещающих template-arguments в последующем template-id, считаются вложенным для целей настоящего описания.