[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]
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 5: 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 template parameter pack, the element is
an id-expression
(for a non-type template parameter pack),
a typedef-name
(for a type template parameter pack declared without template), or
a template-name
(for a type template parameter pack declared with template),
designating the ith corresponding type or value template argument;
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;
otherwise
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 7: 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]