[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]
[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]
[Example 4: auto foo()->int(&)[2];
template<class T>void g(){auto[.a]= foo(); / a is a structured binding pack containing two elementsauto[b, c, ..d]= foo(); / d is a structured binding pack containing zero elements} — end example]
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:
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<unsignedshort, unsigned>::type T1;
/ T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>typedef zip<short>::with<unsignedshort, unsigned>::type T2;
/ error: different number of arguments specified for Args1 and Args2template<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]
if the pack is a function parameter pack, the element is an
id-expression
designating the ith function parameter
that resulted from instantiation of
the function parameter pack declaration;
if the pack is an init-capture pack,
the element is an id-expression
designating the variable introduced by
the ithinit-capture
that resulted from instantiation of
the init-capture pack declaration;
otherwise
if the pack is a structured binding pack,
the element is an id-expression
designating the ith structured binding in the pack
that resulted from the structured binding declaration.
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.
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.
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..);
}templatevoid f<>(); / OK, X<> has no base classes/ x is a variable of type X<> that is value-initialized — end example]