This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[Voted into the WP at the March, 2011 meeting as part of paper N3270.]
Consider an example like:
template <typename T, T Value> struct bar { }; template <typename... T, T ...Value> void foo(bar<T, Value>);
The current wording in 13.2 [temp.param] is unclear as to whether this is permitted or not. For comparison, 9.3.4.6 [dcl.fct] paragraph 13 says,
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 (13.7.4 [temp.variadic]). When it is part of a parameter-declaration-clause, the parameter pack is a function parameter pack (13.7.4 [temp.variadic]). [Note: Otherwise, the parameter-declaration is part of a template-parameter-list and the parameter pack is a template parameter pack; see 13.2 [temp.param]. —end note] A function parameter pack, if present, shall occur at the end of the parameter-declaration-list. 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.
The requirement here that the type of a function parameter pack must contain a template parameter pack is not repeated for template non-type parameters in 13.2 [temp.param], nor is the statement that it expands the template parameter pack.
A related issue is that neither function nor template parameter packs are listed in 13.7.4 [temp.variadic] paragraph 4 among the contexts in which a pack expansion can appear.
Proposed resolution (November, 2010):
Change 7.6.2.5 [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 (13.7.4 [temp.variadic]) by the sizeof... operatorA sizeof... expression is a pack expansion (13.7.4 [temp.variadic]). [Example:...
Change 9.3.4.6 [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 (13.7.4 [temp.variadic]). When it is part of a parameter-declaration-clause, the parameter pack is a function parameter pack (13.7.4 [temp.variadic]). [Note: Otherwise, the parameter-declaration is part of a template-parameter-list and the parameter pack is a template parameter pack; see 13.2 [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 packA function parameter pack is a pack expansion (13.7.4 [temp.variadic]). [Example:...
Change 13.2 [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 (9.3.4.6 [dcl.fct]), then the template-parameter is a template parameter pack (13.7.4 [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. [Example:
template <class... Types> class Tuple; // Types is a template type parameter pack and 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, T... Values> struct static_array; // Values is a non-type template parameter pack and a pack expansion
Change 13.7.4 [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 syntaxconsists 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 (9.3.4.6 [dcl.fct]); the pattern is the parameter-declaration without the ellipsis.
In a template parameter pack that is a pack expansion (13.2 [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 (7.6.2.5 [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
ana pack expansion that is not a sizeof... expression produces a list...The instantiation of a sizeof... expression (7.6.2.5 [expr.sizeof]) produces an integral constant containing the number of elements in the parameter pack it expands.
This resolution also resolves issues 1182 and 1183.
Additional note (February, 2011):
A problematic case is a function like
template<typename... T, T... t> void f(T...) { }
where each element of the nontype pack actually has a different type. This causes problems for template argument deduction, since T and t are supposed to be deduced independently, but they're linked through their sizes. There doesn't appear to be any use case for this kind of example, so it should be ill-formed.
The rule should probably be to consider a non-type template parameter pack that expands any template parameter packs from the same template-parameter-list as ill-formed.