17 Templates [temp]

17.5 Template declarations [temp.decls]

17.5.3 Variadic templates [temp.variadic]

Atemplate parameter pack - это параметр шаблона, который принимает ноль или более аргументов шаблона. [Example:

template<class ... Types> struct Tuple { };

Tuple<> t0;                     // Types contains no arguments
Tuple<int> t1;                  // Types contains one argument: int
Tuple<int, float> t2;           // Types contains two arguments: int and float
Tuple<0> error;                 // error: 0 is not a type

end example]

Afunction parameter pack - это параметр функции, который принимает ноль или более аргументов функции. [Example:

template<class ... Types> void f(Types ... args);

f();                            // OK: args contains no arguments
f(1);                           // OK: args contains one argument: int
f(2, 1.0);                      // OK: args contains two arguments: int and double

end example]

Aparameter pack - это либо пакет параметров шаблона, либо пакет параметров функции.

Apack expansion состоит из apattern и многоточия, создание экземпляра которого дает ноль или более экземпляров шаблона в списке (описанном ниже). Форма паттерна зависит от контекста, в котором происходит расширение. Расширения пакетов могут происходить в следующих контекстах:

[Example:

template<class ... Types> void f(Types ... rest);
template<class ... Types> void g(Types ... rest) {
  f(&rest ...);     // “&rest ...” is a pack expansion; “&rest” is its pattern
}

end example]

Для определения того, удовлетворяет ли пакет параметров правилу в отношении объектов, отличных от пакетов параметров, пакет параметров считается объектом, который может возникнуть в результате реализации шаблона, в котором он появляется.

Пакет параметров, имя которого появляется в шаблоне расширения пакета, расширяется этим расширением пакета. Появление имени пакета параметров расширяется только расширением самого внутреннего охватывающего пакета. Шаблон расширения пакета должен называть один или несколько пакетов параметров, которые не расширяются вложенным расширением пакета; такие пакеты параметров вызываются unexpanded parameter packs в шаблоне. Все пакеты параметров, расширенные расширением пакета, должны иметь одинаковое количество аргументов. Имя пакета параметров, который не раскрывается, отображается неправильно. [Example:

template<typename...> struct Tuple {};
template<typename T1, typename T2> struct Pair {};

template<class ... Args1> struct zip {
  template<class ... Args2> struct with {
    typedef Tuple<Pair<Args1, Args2> ... > type;
  };
};

typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
    // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>
typedef zip<short>::with<unsigned short, unsigned>::type T2;
    // error: different number of arguments specified for Args1 and Args2

template<class ... Args>
  void g(Args ... args) {                   // OK: Args is expanded by the function parameter pack args
    f(const_cast<const Args*>(&args)...);   // OK: “Args” and “args” are expanded
    f(5 ...);                               // error: pattern does not contain any parameter packs
    f(args);                                // error: parameter pack “args” is not expanded
    f(h(args ...) + args ...);              // OK: first “args” expanded within h,
                                            // second “args” expanded within f
  }

end example]

Создание экземпляра расширения пакета, которое не является ниsizeof... выражением, ни a, fold-expression создает список E1,E2,,EN, где N - количество элементов в параметрах расширения пакета. Каждый Ei генерируется путем создания экземпляра шаблона и замены каждого параметра расширения пакета егоith элементом. Такой элемент в контексте создания интерпретируется следующим образом:

  • если пакет является пакетом параметров шаблона, это элементtemplate parameter соответствующего типа (тип или нет), обозначающий тип или значение из аргумента шаблона; иначе,

  • если пакет является пакетом параметров функции, элемент является id-expression обозначением параметра функции, который возник в результате создания экземпляра шаблона, в котором объявлен пакет.

ВсеEi элементы стали в прилагающемся списке. [ Note: Разнообразие списка изменяется в зависимости от контекста: expression-list, base-specifier-list, template-argument-listи т.д. ] Если равен нуль, то конкретизация расширения производит пустой список. Такое создание экземпляра не изменяет синтаксическую интерпретацию включающей конструкции, даже в тех случаях, когда полное исключение списка в противном случае было бы некорректным или привело бы к двусмысленности в грамматике. [end noteN Example:

template<class... T> struct X : T... { };
template<class... T> void f(T... values) {
  X<T...> x(values...);
}

template void f<>();    // OK: X<> has no base classes
                        // x is a variable of type X<> that is value-initialized

end example]

Создание экземпляра asizeof... expression создает целочисленную константу, содержащую количество элементов в расширяемом пакете параметров.

Создание экземпляра a fold-expressionпроизводит:

  • ((E1 opE2) op) opEN для унарной левой складки,

  • E1op (op (EN1op EN)) для унарной правой складки,

  • (((E opE1) opE2) op) opEN для двоичной левой складки, и

  • E1op (op (EN1op (ENop E))) для двоичной правой складки.

В каждом случае op это fold-operator, N является количеством элементов в параметрах расширения пакета, и каждыйEi генерируется инстанцирование шаблона и замены каждого параметра разложения пакета с егоiго элементом. Для двоичного свернутого выражения E создается путем создания экземпляра cast-expression , не содержащего нерасширенного пакета параметров. [Example:

template<typename ...Args>
  bool all(Args ...args) { return (... && args); }

bool b = all(true, true, true, false);

Внутри экземпляраallвозвращаемое выражение расширяется до ((true && true) && true) && false, что дает результатfalse. ] Если для унарного свернутого выражения равно нулю, значение выражения показано в таблице ; если оператор не указан в таблице , создание экземпляра некорректно.end exampleN 1414

Таблица14 - Значение сворачивания пустых последовательностей
ОператорЗначение, когда пакет параметров пуст
&& true
|| false
, void()