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 ]
Apack expansion состоит из apattern и многоточия, создание экземпляра которого дает ноль или более экземпляров шаблона в списке (описанном ниже). Форма паттерна зависит от контекста, в котором происходит расширение. Расширения пакетов могут происходить в следующих контекстах:
В параметре функции pack ([dcl.fct]); узор parameter-declarationбез многоточия.
В a using-declaration; узор - это using-declarator.
В пакете параметров шаблона, который является расширением пакета ([temp.param]):
если пакет параметров шаблона - это parameter-declaration; узор parameter-declarationбез многоточия;
если пакет параметров шаблона - это type-parameterс a template-parameter-list; узор соответствующий type-parameterбез многоточия.
В initializer-list; шаблон initializer-clause.
В a base-specifier-list; узор - это base-specifier.
В a mem-initializer-listдля mem-initializerкоторого mem-initializer-idобозначает базовый класс; шаблон mem-initializer.
В template-argument-list([temp.arg]); узор - это template-argument.
В attribute-list; шаблон attribute.
В alignment-specifier([dcl.align]); узор alignment-specifierбез многоточия.
В capture-list([expr.prim.lambda]); узор - это capture.
В asizeof... expression; шаблон identifier.
В a fold-expression; шаблон - это шаблон, cast-expression который содержит нерасширенный пакет параметров.
[ 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 note N 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 (EN−1op EN)) для унарной правой складки,
(((E opE1) opE2) op⋯) opEN для двоичной левой складки, и
E1op (⋯op (EN−1op (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 example N 1414
Оператор | Значение, когда пакет параметров пуст |
&& | true |
|| | false |
, | void() |