Синтаксис для template-parameters :
template-parameter: type-parameter parameter-declaration
type-parameter: type-parameter-key ...opt identifieropt type-parameter-key identifieropt = type-id template < template-parameter-list > type-parameter-key ...opt identifieropt template < template-parameter-list > type-parameter-key identifieropt = id-expression
type-parameter-key: class typename
[ Маркер следующий за оператором А может быть продукт заменяя маркер на два следующих друг за другом маркеров ( ). ] Note: > template-parameter-listtype-parameter>> >[temp.names] — end note
Нет смысловой разницы между class и typename в type-parameter-key. typename за которым следует unqualified-id имя параметра типа шаблона. typename за которым следует a, qualified-id обозначает тип, не являющийся типом . Форма A - это . [135 parameter-declarationtemplate-parameterclass identifiertype-parameter Example:
class T { /* ... */ }; int i; template<class T, T i> void f(T t) { T t1 = i; // template-parameters T and i ::T t2 = ::i; // global namespace members T and i }
Здесь шаблонf имеет type-parameter вызываемыйT, а не безымянный не тип template-parameterклассаT. ] Класс хранения не должен указываться в декларации. Типы не должны определяться в декларации. — end example template-parametertemplate-parameter
A type-parameter , идентификатор которого не следует за многоточием, определяет его identifier как typedef-name (если он объявлен без template) или template-name (если объявлен с template) в области действия объявления шаблона. [ Note: Аргумент шаблона может быть шаблоном класса или шаблоном псевдонима. Например,
template<class T> class myarray { /* ... */ };
template<class K, class V, template<class T> class C = myarray>
class Map {
C<K> key;
C<V> value;
};
— end note ]
Не-тип template-parameter должен иметь один из следующих (необязательно cv-квалифицированных) типов:
целочисленный или перечислимый тип,
указатель на объект или указатель на функцию,
lvalue ссылка на объект или lvalue ссылка на функцию,
указатель на член,
std::nullptr_t, или
тип, содержащийplaceholder type.
[ Note: Другие типы запрещены либо явно ниже, либо неявно правилами, регулирующими форму template-arguments ([temp.arg]). ] Верхний уровень на игнорируется при определении его типа. — end note cv-qualifierstemplate-parameter
template-parameter Отсутствие ссылки на тип - это prvalue. Его нельзя присвоить или каким-либо иным образом изменить его значение. template-parameter Адрес, не относящийся к типу, не может быть взят. Когда template-parameter в качестве инициализатора для ссылки используется не-типовая не-ссылка, всегда используется временная. [ Example:
template<const X& x, int i> void f() { i++; // error: change of template-parameter value &x; // OK &i; // error: address of non-reference template-parameter int& ri = i; // error: non-const reference bound to temporary const int& cri = i; // OK: const reference bound to temporary }
— end example ]
Не-тип template-parameter нельзя объявлять как имеющий тип с плавающей запятой, класс или тип void. [ Example:
template<double d> class X; // error template<double* pd> class Y; // OK template<double& rd> class Z; // OK
— end example ]
Не тип типа «массив » или типа функции настраивается на тип «указатель на ». [template-parameter TTT Example:
template<int* a> struct R { /* ... */ }; template<int b[5]> struct S { /* ... */ }; int p; R<&p> w; // OK S<&p> x; // OK due to parameter adjustment int v[5]; R<v> y; // OK due to implicit argument conversion S<v> z; // OK due to both adjustment and conversion
— end example ]
A default template-argument - это template-argument([temp.arg]), указанный после = в a template-parameter. Значение по умолчанию template-argument может быть указано для любого типа template-parameter (тип, не тип, шаблон), кроме файла template parameter pack. Значение по умолчанию template-argument может быть указано в объявлении шаблона. Значение по умолчанию template-argument не должно указываться в template-parameter-lists определении члена шаблона класса, который появляется вне класса члена. Значение по умолчанию template-argument не должно указываться в объявлении шаблона дружественного класса. Если объявление шаблона функции друга указывает значение по умолчанию template-argument, это объявление должно быть определением и должно быть единственным объявлением шаблона функции в единице перевода.
Набор template-arguments доступных для использования значений по умолчанию получается путем объединения аргументов по умолчанию из всех предыдущих объявлений шаблона таким же образом, как аргументы функции по умолчанию ([dcl.fct.default]). [ Example:
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
эквивалентно
template<class T1 = int, class T2 = int> class A;
— end example ]
Если template-parameter шаблон класса, шаблон переменной или шаблон псевдонима имеет значение по умолчанию template-argument, каждый последующий template-parameter должен либо иметь значение по умолчанию, template-argument либо быть пакетом параметров шаблона. Если a template-parameter из шаблона первичного класса, шаблона первичной переменной или шаблона псевдонима является пакетом параметров шаблона, он должен быть последним template-parameter. За пакетом параметров шаблона шаблона функции не должен следовать другой параметр шаблона, если только этот параметр шаблона не может быть выведен из списка-типа-параметра ([dcl.fct]) шаблона функции или имеет аргумент по умолчанию ([temp.deduct]). Параметр шаблона для шаблона руководства по вычету ([temp.deduct.guide]), у которого нет аргумента по умолчанию, должен выводиться из списка типов-параметров шаблона руководства по вычету. [ Example:
template<class T1 = int, class T2> class B; // error // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error template<class... T, class U> void g() { } // error
— end example ]
template-parameter Не дадутся по умолчанию аргументов два различных деклараций в том же объеме. [ Example:
template<class T = int> class X; template<class T = int> class X { /* ... */ }; // error
— end example ]
При синтаксическом разборе значения template-argument по умолчанию для не-типа template-parameterпервое невложенное значение > считается концом, template-parameter-list а не оператором "больше чем". [ Example:
template<int i = 3 > 4 > // syntax error class X { /* ... */ }; template<int i = (3 > 4) > // OK class Y { /* ... */ };
— end example ]
Для template-parameter шаблона template-parameter разрешено иметь значение по умолчанию template-argument. Когда такие аргументы по умолчанию указаны, они применяются к шаблону template-parameter в области действия шаблона template-parameter. [ Example:
template <class T = float> struct B {}; template <template <class TT = float> class T> struct A { inline void f(); inline void g(); }; template <template <class TT> class T> void A<T>::f() { T<> t; // error - TT has no default template argument } template <template <class TT = char> class T> void A<T>::g() { T<> t; // OK - T<char> }
— end example ]
Если a template-parameter- type-parameterс многоточием перед необязательным identifierили является a, parameter-declarationкоторый объявляет параметр pack ([dcl.fct]), то template-parameter это atemplate parameter pack. Пакет параметров шаблона parameter-declaration, тип которого содержит один или несколько нерасширенных пакетов параметров, является расширением пакета. Аналогичным образом , параметр пакет шаблона , который является type-parameterс , template-parameter-listсодержащими один или более пакетами нерасширенных параметров является пакет расширения. Пакет параметров шаблона, который является расширением пакета, не должен расширять пакет параметров, объявленный в нем template-parameter-list. [ Example:
template <class... Types> class Tuple; // Types is a template type parameter pack // but not a pack expansion template <class T, int... Dims> struct multi_array; // Dims is a non-type template parameter pack // but not a pack expansion template<class... T> struct value_holder { template<T... Values> struct apply { }; // Values is a non-type template parameter pack // and a pack expansion }; template<class... T, T... Values> struct static_array;// error: Values expands template type parameter // pack T within the same template parameter list
— end example ]
Поскольку шаблон template-parameters и шаблон template-arguments рассматриваются как типы в описательных целях, термины non-type parameter и non-type argument используются для обозначения параметров и аргументов, не являющихся типом и шаблоном.