[temp.variadic] (original) (raw)

13 Templates [temp]

13.7 Template declarations [temp.decls]

13.7.4 Variadic templates [temp.variadic]

A template parameter pack is a template parameter that accepts zero or more template arguments.

[Example 1: template<class ... Types> struct Tuple { }; Tuple<> t0; Tuple<int> t1; Tuple<int, float> t2; Tuple<0> error; — _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(); f(1); f(2, 1.0); — _end example_]

[Example 3: template <typename... Args> void foo(Args... args) { [...xs=args]{ bar(xs...); };}foo(); foo(1); — _end example_]

A pack is a template parameter pack, a function parameter pack, or an init-capture 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 expansionconsists 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 4: template<class ... Types> void f(Types ... rest);template<class ... Types> void g(Types ... rest) { f(&rest ...); } — _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 calledunexpanded 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<unsigned short, unsigned>::type T1;typedef zip<short>::with<unsigned short, unsigned>::type T2;template<class ... Args> void g(Args ... args) { f(const_cast<const Args*>(&args)...); f(5 ...); f(args); f(h(args ...) + args ...); } — _end example_]

The instantiation of a pack expansion considers items , whereN is the number of elements in the pack expansion parameters.

Each is generated by instantiating the pattern and replacing each pack expansion parameter with its element.

Such an element, in the context of the instantiation, is interpreted as follows:

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.

The instantiation of a fold-expression ([expr.prim.fold]) produces:

For a binary fold,E is generated by instantiating the cast-expressionthat did not contain an unexpanded pack.

[Example 6: template<typename ...Args> bool all(Args ...args) { return (... && args); } bool b = all(true, 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
🔗 |
🔗 , void()

The instantiation of any other pack expansion produces a list of elements .

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...);} template void f<>(); — _end example_]