Reputation: 1709
Quote from the Standard:
The type-id in a trailing-return-type includes the longest possible sequence of abstract-declarators.
Note: This resolves the ambiguous binding of array and function declarators.
Example:
auto f()->int(*)[4]; // function returning a pointer to array[4] of int
// not function returning array[4] of pointer to int
I'm wondering, what is ambiguous with this given code?
Ambiguities that are mentioned in the Standard are usually due to the ambiguity of the grammar itself, while in this case given character sequence is always interpreted as a trailing return type (i.e. a single type), and there shouldn't be ambiguity on which one it is.
By the way, why type-id is referred to? I mean, formally it can only occur in different places of code than trailing-return-type. Or is it just informally mentioned since everything that can be parsed (by itself) as trailing-return-type can be parsed as type-id (by itself) as well? I'm just not that well-aware of when nonterminals are used in the Standard...
Upvotes: 1
Views: 141
Reputation: 15908
In N2541, a trailing-return-type may appear in any function declarator. That means auto (*f() -> int);
is a valid declaration. At that time auto f()->int(*)[4];
may be interpreted as having the same meaning of auto (f()->int(*))[4];
(declare f
as function returning array[4] of pointer to int). It may also be interpreted in the way we normally expect, i.e. [4]
is a part of the trailing-return-type and the declaration declares a function returning a pointer to array[4] of int. The quoted paragraph was added at that time to resolve this ambiguity.
After N2541 was voted into the standard, CWG 681 changed the grammar to ensure that a trailing-return-type may only appear in the top level function declarator; therefore [4]
has to be a part of the trailing-return-type. There is no longer any ambiguity. However, CWG 681 does not remove the disambiguation rule, which seems to be an oversight.
That oversight was recently corrected by CWG 2040, which removed the now-useless paragraph.
N2541 also allows a type-id to appear after the symbol ->
, which brings an ambiguity in declarations like auto f() -> struct S { };
. This is CWG 770 and is resolved by N2927, which defines trailing-return-type as the symbol ->
followed by a trailing-type-specifier-seq followed by an optional abstract-declarator. However N2927 does not modify the disambiguation rule, even though it makes no sense now that there's no type-id in a trailing-return-type.
A type-id is a type-specifier-seq followed by an optional abstract-declarator. At that time a class type or enumeration type definition might appear in a type-specifier-seq but not in a trailing-type-specifier-seq. This made -> struct S {}
an invalid trailing-return-type, though struct S {}
was a valid type-id.
The grammar was changed again lately by CWG 2141, which renames type-specifier-seq to defining-type-specifier-seq and renames trailing-type-specifier-seq to type-specifier-seq. A type-id is still defined as a type-specifier-seq followed by an optional abstract-declarator. The end result is that a class type or enumeration type definition now may not appear in a type-id. Now again, any type-id may appear after the symbol ->
in a trailing-return-type.
Upvotes: 1