17 Templates [temp]

17.2 Names of template specializations [temp.names]

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 noteExample:

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 noteNote: typenametemplatenested-name-specifier->.template-parameterend noteExample:

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]

А, simple-template-id который называет специализацию шаблона класса, является class-name.

А, template-idкоторый называет специализацию шаблона псевдонима, является type-name.

> , Покрывающие type-id из dynamic_­cast, static_­cast, reinterpret_­cast или const_­cast, или, вмещающих template-arguments в последующем template-id, считаются вложенным для целей настоящего описания.