This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2026-05-08
(From submission #889.)
Consider:
template<class T>
struct S {
using U = decltype((void)(T*)0);
void f(U); // #1
};
template<class T>
void S<T>::f() {} // redeclaration of #1?
Also consider:
template<class T>
struct S {
void f(std::void_t<T*>); // #1
};
S<int> x; // #1 is a zero-parameter function or has an ill-formed parameter of type void
The current phrasing in 9.3.4.6 [dcl.fct] paragraph 2 is the result of core issues 577 and 2915. The current rule, enabling typedefs for void, is primarily motivated by C compatibility.
Possible resolution (2026-04-22) [SUPERSEDED]:
Change in 9.3.4.6 [dcl.fct] paragraph 3 as follows and split into two paragraphs:
The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called. [Note 1: The parameter-declaration-clause is used to convert the arguments specified on the function call; see 7.6.1.3 [expr.call]. —end note] If the parameter-declaration-clause is empty, the function takes no arguments. A parameter list (void) and, for a non-templated function, a parameter list consisting of a single unnamed non-object parameter of
non-dependenttype voidisare equivalent to an empty parameter list. Except forthisthese specialcasecases, a parameter shall not have type cv void. A parameter with volatile-qualified type is deprecated; see D.4 [depr.volatile.type].If the parameter-declaration-clause terminates with an ellipsis or a function parameter pack (13.7.4 [temp.variadic]), the number of arguments shall be equal to or greater than the number of parameters that do not have a default argument and are not function parameter packs. Where syntactically correct and where “...” is not part of an abstract-declarator , “...” is synonymous with “, ...”. A parameter-declaration-clause of the form parameter-declaration-list ... is deprecated (D.5 [depr.ellipsis.comma]). ...
CWG 2026-04-28
Despite the fact that "equivalent type" is not well-defined (see issue 2584), the most appropriate approach is to use "equivalent type". Both examples above are ill-formed.
Proposed resolution (approved by CWG 2026-05-08):
Change in 9.3.4.6 [dcl.fct] paragraph 3 as follows and split into two paragraphs:
The parameter-declaration-clause determines the arguments that can be specified, and their processing, when the function is called. [Note 1: The parameter-declaration-clause is used to convert the arguments specified on the function call; see 7.6.1.3 [expr.call]. —end note] If the parameter-declaration-clause is empty, the function takes no arguments. A parameter list consisting of a single unnamed non-object parameter of
non-dependentsome type T, where T is equivalent to (13.7.7.2 [temp.over.link]) void, is equivalent to an empty parameter list. Except for this special case, a parameter shall not have type cv void. A parameter with volatile-qualified type is deprecated; see D.4 [depr.volatile.type].[ Example:template<class T> struct S { void f(std::void_t<T*>); // #1 }; S<int> x; // error: #1 has a parameter of type void template<class T> struct S2 { void f(std::void_t<int*>); // #2 }; S2<int> y; // OK, #2 is a zero-parameter function-- end example ]If the parameter-declaration-clause terminates with an ellipsis or a function parameter pack (13.7.4 [temp.variadic]), the number of arguments shall be equal to or greater than the number of parameters that do not have a default argument and are not function parameter packs. Where syntactically correct and where “...” is not part of an abstract-declarator , “...” is synonymous with “, ...”. A parameter-declaration-clause of the form parameter-declaration-list ... is deprecated (D.5 [depr.ellipsis.comma]). ...