#
A template parameter pack is a template parameter that accepts zero or more template arguments.
[Example 1: 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]
A function parameter pack is a function parameter that accepts zero or more function arguments.
[Example 2: template<class .. Types> void f(Types .. args); f(); / args contains no arguments f(1); / args contains one argument: int f(2, 1.0); / args contains two arguments: int and double — end example]
An init-capture pack is a lambda capture that introduces an init-capture for each of the elements in the pack expansion of its initializer.
[Example 3: template <typename. Args> void foo(Args.. args) { [.xs=args]{ bar(xs..); / xs is an init-capture pack }; } foo(); / xs contains zero init-captures foo(1); / xs contains one init-capture — end example]
A structured binding pack is an sb-identifier that introduces zero or more structured bindings ([dcl.struct.bind]).
[Example 4: auto foo() -> int(&)[2]; template <class T> void g() { auto [.a] = foo(); / a is a structured binding pack containing two elements auto [b, c, ..d] = foo(); / d is a structured binding pack containing zero elements } — end example]
A pack is a template parameter pack, a function parameter pack, an init-capture pack, or a structured binding pack.
The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack.
The number of elements of an init-capture pack is the number of elements in the pack expansion of its initializer.
A pack expansion consists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below).
The form of the pattern depends on the context in which the expansion occurs.
Pack expansions can occur in the following contexts:
[Example 5: 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]
For the purpose of determining whether a pack satisfies a rule regarding entities other than packs, the pack is considered to be the entity that would result from an instantiation of the pattern in which it appears.
A pack whose name appears within the pattern of a pack expansion is expanded by that pack expansion.
An appearance of the name of a pack is only expanded by the innermost enclosing pack expansion.
The pattern of a pack expansion shall name one or more packs that are not expanded by a nested pack expansion; such packs are called unexpanded packs in the pattern.
All of the packs expanded by a pack expansion shall have the same number of arguments specified.
An appearance of a name of a pack that is not expanded is ill-formed.
[Example 6: 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 packs f(args); / error: pack “args'' is not expanded f(h(args ..) + args ..); / OK, first “args'' expanded within h, / second “args'' expanded within f } — end example]
The instantiation of a pack expansion considers items
Each
Such an element, in the context of the instantiation, is interpreted as follows:
  • if the pack is a template parameter pack, the element is designating the
  • if the pack is a function parameter pack, the element is an id-expression designating the
  • if the pack is an init-capture pack, the element is an id-expression designating the variable introduced by the
  • if the pack is a structured binding pack, the element is an id-expression designating the
When N is zero, the instantiation of a pack expansion does not alter the syntactic interpretation of the enclosing construct, even in cases where omitting the pack expansion entirely would otherwise be ill-formed or would result in an ambiguity in the grammar.
The instantiation of a sizeof. expression ([expr.sizeof]) produces an integral constant with value N.
When instantiating a pack-index-expression P, let K be the index of P.
The instantiation of P is the id-expression
When instantiating a pack-index-specifier P, let K be the index of P.
The instantiation of P is the typedef-name
The instantiation of an alignment-specifier with an ellipsis produces
The instantiation of a fold-expression ([expr.prim.fold]) produces:
  • ( ((
  • (
  • ( ((E op
  • (
In each case, op is the fold-operator.
For a binary fold, E is generated by instantiating the cast-expression that did not contain an unexpanded pack.
[Example 7: template<typename ..Args> bool all(Args ..args) { return (. && args); } bool b = all(true, true, false);
Within the instantiation of all, the returned expression expands to ((true && true) && true) && false, which evaluates to false.
— end example]
If N is zero for a unary fold, the value of the expression is shown in Table 20; if the operator is not listed in Table 20, the instantiation is ill-formed.
Table 20 — Value of folding empty sequences [tab:temp.fold.empty]
Operator
Value when pack is empty
&&
true
||
false
,
void()
The instantiation of any other pack expansion produces a list of elements
[Note 1: 
The variety of list varies with the context: expression-list, base-specifier-list, template-argument-list, etc.
— end note]
When N is zero, the instantiation of the expansion produces an empty list.
[Example 8: 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]

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant