Как и обычные (не шаблонные) классы, шаблоны классов имеют расширение injected-class-name. Введенное-имя-класса может использоваться как template-nameили type-name. Когда он используется с template-argument-list, как template-argumentдля шаблона template-parameterили как окончательный идентификатор в elaborated-type-specifierобъявлении шаблона дружественного класса, он ссылается на сам шаблон класса. В противном случае, это равносильно тому , template-name сопровождаемое template-parameters шаблон класса , заключенном в <>.
В рамках специализации шаблона класса или частичной специализации, когда имя injected-class-name используется как a type-name, оно эквивалентно, за template-nameкоторым следует template-arguments специализация шаблона класса или частичная специализация, заключенная в <>. [ Example:
template<template<class> class T> class A { }; template<class T> class Y; template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<::Y> class B { template<class> friend class Y; // meaning ::Y }; };
— end example ]
Нагнетаемого класса имя шаблона класса или класса специализации шаблона может быть использован либо как template-nameили type-name там , где она находится в области видимости. [ Example:
template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived::Base<T> }; template<class T, template<class> class U = T::template Base> struct Third { }; Third<Base<int> > t; // OK: default argument uses injected-class-name as a template
— end example ]
Поиск, который находит внедренное имя-класса ([class.member.lookup]), в некоторых случаях может привести к неоднозначности (например, если он найден более чем в одном базовом классе). Если все найденные имена внедренных классов относятся к специализациям одного и того же шаблона класса, и если имя используется как a template-name, ссылка относится к самому шаблону класса, а не к его специализации, и не является двусмысленной. [ Example:
template <class T> struct Base { }; template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; // error: ambiguous typename Derived::Base<double> d; // OK };
— end example ]
Когда используется обычное имя шаблона (т. Е. Имя из охватывающей области, а не внедренное имя-класса), оно всегда относится к самому шаблону класса, а не к его специализации. [ Example:
template<class T> class X { X* p; // meaning X<T> X<T>* p2; X<int>* p3; ::X* p4; // error: missing template argument list // ::X does not refer to the injected-class-name };
— end example ]
A template-parameter не следует повторно объявлять в пределах своей области действия (включая вложенные области действия). Имя A template-parameter не должно совпадать с именем шаблона. [ Example:
template<class T, int i> class Y { int T; // error: template-parameter redeclared void f() { char T; // error: template-parameter redeclared } }; template<class X> class X; // error: template-parameter redeclared
— end example ]
В определении члена шаблона класса, который появляется вне определения шаблона класса, имя члена шаблона класса скрывает имя template-parameter любого включающего шаблона класса (но не template-parameterчлена, если член является шаблон класса или функции). [ Example:
template<class T> struct A { struct B { /* ... */ }; typedef void C; void f(); template<class U> void g(U); }; template<class B> void A<B>::f() { B b; // A's B, not the template parameter } template<class B> template<class C> void A<B>::g(C) { B b; // A's B, not the template parameter C c; // the template parameter C, not A's C }
— end example ]
В определении члена шаблона класса, который появляется за пределами пространства имен, содержащего определение шаблона класса, имя template-parameter скрывает имя члена этого пространства имен. [ Example:
namespace N {
class C { };
template<class T> class B {
void f(T);
};
}
template<class C> void N::B<C>::f(C) {
C b; // C is the template parameter, not N::C
}
— end example ]
В определении шаблона класса или в определении члена такого шаблона, который появляется вне определения шаблона, для каждого независимого базового класса ([temp.dep.type]), если имя базового класса или имя члена базовый класс такой же , как название template-parameter, имя базового класса или члена имя hides на template-parameter имя. [ Example:
struct A { struct B { /* ... */ }; int a; int Y; }; template<class B, class a> struct X : A { B b; // A's B a b; // error: A's a isn't a type name };
— end example ]