This paper addresses the following three issues with variadic templates:
Proposed resolution:
Change 5.3.3 [expr.sizeof] paragraph 5 as follows:
The identifier in a sizeof... expression shall name a parameter pack. The sizeof... operator yields the number of arguments provided for the parameter pack identifier. The parameter pack is expanded (14.5.3 [temp.variadic]) by the sizeof... operator A sizeof... expression is a pack expansion (14.5.3 [temp.variadic]). [Example:...
Change 8.3.5 [dcl.fct] paragraph 13 as follows:
A declarator-id or abstract-declarator containing an ellipsis shall only be used in a parameter-declaration. Such a parameter-declaration is a parameter pack (14.5.3 [temp.variadic]). When it is part of a parameter-declaration-clause, the parameter pack is a function parameter pack (14.5.3 [temp.variadic]). [Note: Otherwise, the parameter-declaration is part of a template-parameter-list and the parameter pack is a template parameter pack; see 14.1 [temp.param]. —end note] The type T of the declarator-id of the function parameter pack shall contain a template parameter pack; each template parameter pack in T is expanded by the function parameter pack A function parameter pack is a pack expansion (14.5.3 [temp.variadic]). [Example:...
Change 14.1 [temp.param] paragraph 15 as follows:
If a template-parameter is a type-parameter with an ellipsis prior to its optional identifier or is a parameter-declaration that declares a parameter pack (8.3.5 [dcl.fct]), then the template-parameter is a template parameter pack (14.5.3 [temp.variadic]). A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded parameter packs is a pack expansion. Similarly, a template parameter pack that is a type-parameter with a template-parameter-list containing one or more unexpanded parameter packs is a pack expansion. A template parameter pack that is a pack expansion shall not expand a parameter pack declared in the same template-parameter-list. [Example:
template <class ...Types> class Tuple; // Types is a template type parameter pack but not a pack expansion template <class T, int ...Dims> struct multi_array; // Dims is a non-type template parameter pack but not a pack expansion template<class ...T> struct value_holder { template<T ...Values> apply { }; // Values is a non-type template parameter pack and a pack expansion }; template <class ...T, T ...Values> struct static_array; // Error: Values expands template type parameter pack T within the same template parameter list
Change 14.5.3 [temp.variadic] paragraphs 4-6 and add a new paragraph 7 as follows:
A pack expansion is a sequence of tokens that names one or more parameter packs, followed by an ellipsis. The sequence of tokens is called the pattern of the expansion; its syntax 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:
In a function parameter pack (8.3.5 [dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
In a template parameter pack that is a pack expansion (14.1 [temp.param]):
if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration without the ellipsis,
if the template parameter pack is a type-parameter with a template-parameter-list; the pattern is the corresponding type-parameter without the ellipsis.
...
In a sizeof... expression (5.3.3 [expr.sizeof]), the pattern is an identifier.
[Example:...
A parameter pack whose name appears within the pattern of a pack expansion is expanded by that pack expansion. An appearance of the name of a parameter pack is only expanded by the innermost enclosing pack expansion. The pattern of a pack expansion shall name one or more parameter packs that are not expanded by a nested pack expansion; such parameter packs are called unexpanded parameter packs in the pattern. All of the parameter packs expanded...
... void g(Args ... args) { // OK: Args is expanded by the function parameter pack args ...
The instantiation of an a pack expansion that is not a sizeof... expression produces a list...
The instantiation of a sizeof... expression (5.3.3 [expr.sizeof]) produces an integral constant containing the number of elements in the parameter pack it expands.