This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Accepted as a DR at the March, 2024 meeting.]
According to 9.2.9.7.1 [dcl.spec.auto.general] paragraph 3,
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid. If the function declarator includes a trailing-return-type (9.3.4.6 [dcl.fct]), that trailing-return-type specifies the declared return type of the function. Otherwise, the function declarator shall declare a function.
This wording disallows a declaration like
int f(); auto (*fp)()=f;
The requirement to declare a function was introduced by the resolution of issue 1892.
Proposed resolution (April, 2021) [SUPERSEDED]:
Change 9.2.9.7.1 [dcl.spec.auto.general] paragraph 3 as follows:
The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is validif the function declarator includes a trailing-return-type T (9.3.4.6 [dcl.fct]) or declares a function.If the function declarator includes a trailing-return-type (9.3.4.6 [dcl.fct]), that trailing-return-type specifiesIn the former case, T is the declared return type of the function.Otherwise, the function declarator shall declare a function.If the declared return type ofthea function contains a placeholder type, the return type of the function is deduced from non-discarded return statements, if any, in the body of the function (8.5.2 [stmt.if]).
Additional notes (May, 2021):
It was observed that the proposed resolution above does not address the example in the issue, since fp neither has a trailing-return-type nor declares a function. Presumably another case in which a function declarator with a placeholder return type should be permitted is in the declaration of a variable in which the type is deduced from its initializer.
It was also noted in passing that the deduction in the example is only partial: the parameter-type-list is specified by the declarator and only the return type is deduced from the initializer. Although this example is supported by current implementations, there is implementation divergence in the support of another case in which only part of the variable's type is deduced:
auto (&ar)[2] = L"a"; // Array bound declared, element type deduced
This issue is related to issue 1892, which prohibited cases like
std::vector<auto(*)()> v;
The ultimate outcome of the two issues should be:
int f(); auto (*fp1)() = f; // OK auto (*fp2)()->int = f; // OK auto (*fp3)()->auto = f; // OK template<typename T> struct C { }; C<auto(*)()> c1; // Not OK C<auto(*)()->int> c2; // OK C<auto(*)()->auto> c3; // Not OK
Proposed resolution (January, 2023) [SUPERSEDED]:
Change in 9.2.9.7.1 [dcl.spec.auto.general] paragraph 1 as follows:
A placeholder-type-specifier designates a placeholder type that will be replaced later, typically by deduction from an initializer.
Change and split 9.2.9.7.1 [dcl.spec.auto.general] paragraph 3 as follows:
A placeholder type can appear
with a function declaratorin the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where suchfor a function declaratoris validthat includes a trailing-return-type (9.3.4.6 [dcl.fct]).If the function declarator includes a trailing-return-type (9.3.4.6 [dcl.fct]), that trailing-return-type specifies the declared return type of the function.
Otherwise, theA placeholder type can appear in the decl-specifier-seq or type-specifier-seq in the declared return type of a function declaratorshall declarethat declares a function. If the declared return type of the function contains a placeholder type,; the return type of the function is deduced from non-discarded return statements, if any, in the body of the function (8.5.2 [stmt.if]).
Change in 9.2.9.7.1 [dcl.spec.auto.general] paragraph 4 as follows:
The type of a variable declared using a placeholder type is deduced from its initializer. This use is allowed in an initializing declaration (9.4 [dcl.init]) of a variable. The placeholder type shall appear as one of the decl-specifiers in the decl-specifier-seqandor as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a decl-specifier; the decl-specifier-seq shall be followed by one or more declarators, each of which shall be followed by a non-empty initializer. [ Example:... auto f() -> int; // OK, f returns int auto (*fp)() -> auto = f; // OK ...-- end example ]
Change in 9.3.4.6 [dcl.fct] paragraph 1 as follows:
In a declaration T D where D has the formD1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt noexcept-specifieropt attribute-specifier-seqopt trailing-return-typeoptand the type of the contained declarator-id in the declaration T D1 is "derived-declarator-type-list T",:
- If the trailing-return-type is present, T shall be the single type-specifier auto, and the declared return type of the function type is the type specified by the trailing-return-type.
- Otherwise, the declared return type of the function type is T.
theThe type of the declarator-id in D is "derived-declarator-type-list noexceptopt function of parameter-type-list cv-qualifier-seqopt ref-qualifieropt returningTU", whereThe optional attribute-specifier-seq appertains to the function type.
- the parameter-type-list is derived from the parameter-declaration-clause as described below,
- U is the declared return type, and
- the optional noexcept is present if and only if the exception specification (14.5 [except.spec]) is non-throwing.
Remove 9.3.4.6 [dcl.fct] paragraph 2:
In a declaration T D where D has the formand the type ... The optional attribute-specifier-seq appertains to the function type.D1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt noexcept-specifieropt attribute-specifier-seqopt trailing-return-type
Change in 11.4.8.3 [class.conv.fct] paragraph 1 as follows:
A declaration whose declarator-id has an unqualified-id that is a conversion-function-id declares a conversion function; its declarator shall be a function declarator (9.3.4.6 [dcl.fct]) of the formwhere theptr-declaratornoptr-declarator( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifier-seqopt noexcept-specifieropt attribute-specifier-seqoptparameters-and-qualifiersptr-declaratornoptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms: ...
Change in 11.4.8.3 [class.conv.fct] paragraph 2 as follows:
A conversion function shall have no non-object parameters and shall be a non-static member function of a class or class template X; its declared return type is the conversion-type-id and it specifies a conversion from X to the type specified by the conversion-type-id interpreted as a type-id (9.3.2 [dcl.name]). A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall not be a defining-type-specifier .
Remove 11.4.8.3 [class.conv.fct] paragraph 3:
The type of the conversion function is “noexceptopt function taking no parameter cv-qualifier-seq opt ref-qualifier opt returning conversion-type-id”.
CWG 2023-06
This does not address void f2(auto (*)() -> auto);
Proposed resolution (approved by CWG 2023-11-10):
Change in 9.2.9.7.1 [dcl.spec.auto.general] paragraph 1 as follows:
A placeholder-type-specifier designates a placeholder type that will be replaced later, typically by deduction from an initializer.
Change 9.2.9.7.1 [dcl.spec.auto.general] paragraph 2 as follows:
AThe type of a parameter-declaration of a function declaration (9.3.4.6 [dcl.fct]), lambda-expression (7.5.6 [expr.prim.lambda]), or template-parameter (13.2 [temp.param]) can be declared using a placeholder-type-specifier of the form type-constraintopt autocan be used as a decl-specifier of the decl-specifier-seq of a parameter-declaration of a function declaration or lambda-expression and, if it is not the auto type-specifier introducing. The placeholder type shall appear as one of the decl-specifiers in the decl-specifier-seq or as one of the type-specifiers in a trailing-return-type,that specifies the type that replaces such a decl-specifier (see below); the placeholder type is a generic parameter type placeholder of the function declarationor, lambda-expression, or template-parameter, respectively.
Change and split 9.2.9.7.1 [dcl.spec.auto.general] paragraph 3 as follows:
A placeholder type can appear
with a function declaratorin the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where suchfor a function declaratoris validthat includes a trailing-return-type (9.3.4.6 [dcl.fct]).If the function declarator includes a trailing-return-type (9.3.4.6 [dcl.fct]), that trailing-return-type specifies the declared return type of the function.
Otherwise, theA placeholder type can appear in the decl-specifier-seq or type-specifier-seq in the declared return type of a function declaratorshall declarethat declares a function. If the declared return type of the function contains a placeholder type,; the return type of the function is deduced from non-discarded return statements, if any, in the body of the function (8.5.2 [stmt.if]).
Change in 9.2.9.7.1 [dcl.spec.auto.general] paragraph 4 as follows:
The type of a variable declared using a placeholder type is deduced from its initializer. This use is allowed in an initializing declaration (9.4 [dcl.init]) of a variable. The placeholder type shall appear as one of the decl-specifiers in the decl-specifier-seqandor as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a decl-specifier; the decl-specifier-seq shall be followed by one or more declarators, each of which shall be followed by a non-empty initializer. [ Example:... auto f() -> int; // OK, f returns int auto (*fp)() -> auto = f; // OK ...-- end example ]
Change and split 9.2.9.7.1 [dcl.spec.auto.general] paragraph 5 as follows:
A placeholder type can also be used in the type-specifier-seq
inof the new-type-id or in the type-id of a new-expression (7.6.2.8 [expr.new])and as a decl-specifier of the parameter-declaration's decl-specifier-seq in a template-parameter (13.2 [temp.param]). In such a type-id, the placeholder type shall appear as one of the type-specifiers in the type-specifier-seq or as one of the type-specifiers in a trailing-return-type that specifies the type that replaces such a type-specifier.The auto type-specifier can also be used as the simple-type-specifier in an explicit type conversion (functional notation) (7.6.1.4 [expr.type.conv]).
Change in 9.3.4.6 [dcl.fct] paragraph 1 as follows:
In a declaration T D where T may be empty and D has the formD1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt noexcept-specifieropt attribute-specifier-seqopt trailing-return-typeopta derived-declarator-type-list is determined as follows:andThe declared return type U of the function type is determined as follows:
- If the unqualified-id of the declarator-id is a conversion-function-id, the derived-declarator-type-list is empty.
- Otherwise, the derived-declarator-type-list is as appears in the type "derived-declarator-type-list T" of the contained declarator-id in the declaration T D1
is "derived-declarator-type-list T".
- If the trailing-return-type is present, T shall be the single type-specifier auto, and U is the type specified by the trailing-return-type.
- Otherwise, if the declaration declares a conversion function, see 11.4.8.3 [class.conv.fct].
- Otherwise, U is T.
theThe type of the declarator-id in D is "derived-declarator-type-list noexceptopt function of parameter-type-list cv-qualifier-seqopt ref-qualifieropt returningTU", whereThe optional attribute-specifier-seq appertains to the function type.
- the parameter-type-list is derived from the parameter-declaration-clause as described below and
- the optional noexcept is present if and only if the exception specification (14.5 [except.spec]) is non-throwing.
Remove 9.3.4.6 [dcl.fct] paragraph 2:
In a declaration T D where D has the formand the type ... The optional attribute-specifier-seq appertains to the function type.D1 ( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifieropt noexcept-specifieropt attribute-specifier-seqopt trailing-return-type
Change in 11.4.8.3 [class.conv.fct] paragraph 1 as follows:
A declaration whose declarator-id has an unqualified-id that is a conversion-function-id declares a conversion function; its declarator shall be a function declarator (9.3.4.6 [dcl.fct]) of the formwhere theptr-declaratornoptr-declarator( parameter-declaration-clause ) cv-qualifier-seqopt ref-qualifier-seqopt noexcept-specifieropt attribute-specifier-seqoptparameters-and-qualifiersptr-declaratornoptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms: ...
Change in 11.4.8.3 [class.conv.fct] paragraph 2 as follows:
A conversion function shall have no non-object parameters and shall be a non-static member function of a class or class template X; its declared return type is the conversion-type-id and it specifies a conversion from X to the type specified by the conversion-type-id interpreted as a type-id (9.3.2 [dcl.name]). A decl-specifier in the decl-specifier-seq of a conversion function (if any) shall not be a defining-type-specifier .
Remove 11.4.8.3 [class.conv.fct] paragraph 3:
The type of the conversion function is “noexceptopt function taking no parameter cv-qualifier-seq opt ref-qualifier opt returning conversion-type-id”.