17 Templates [temp]

17.1 Template parameters [temp.param]

Синтаксис для 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-parameterExample:

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 exampletemplate-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 notecv-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 TTTExample:

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 используются для обозначения параметров и аргументов, не являющихся типом и шаблоном.