6
votes

g++ appears to accept any combination of auto and decltype(auto) as initial and trailing return types:

int a;
auto f() { return (a); }                             // int
auto g() -> auto { return (a); }                     // int
auto h() -> decltype(auto) { return (a); }           // int&
decltype(auto) i() { return (a); }                   // int&
decltype(auto) j() -> auto { return (a); }           // int
decltype(auto) k() -> decltype(auto) { return (a); } // int&

However, clang rejects j and k, saying: error: function with trailing return type must specify return type 'auto', not 'decltype(auto)' (demonstration).

Which compiler is correct? Which rule (auto or decltype(auto)) should be used in each case? And does it make any sense to use a placeholder type in a trailing-return-type?

2

2 Answers

14
votes

auto is required when introducing a trailing-return-type.

§8.3.5 [dcl.fct] /2

In a declaration T D where D has the form

D1 ( parameter-declaration-clause ) cv-qualifier-seqoptref-qualifieroptexception-specificationoptattribute-specifier-seqopttrailing-return-type

and the type of the contained declarator-id in the declaration T D1 is “derived-declarator-type-list T”,

T shall be the single type-specifier auto. [...]

See also Core Issue 1852 for the apparent contradiction with [dcl.spec.auto]/1.

3
votes

Edit after @Xeo constructive comments:

It seems that this issue is due a contradiction between two places of the draft standard.

According to the draft standard § 7.1.6.4 auto specifier [dcl.spec.auto]:

1 The auto and decltype(auto) type-specifiers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a trailing-return-type. The auto type-specifier is also used to signify that a lambda is a generic lambda.

2 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 (8.3.5), that specifies the declared return type of the function. If the declared return type of the function contains a placeholder type, the return type of the function is deduced from return statements in the body of the function, if any.

The sole interpretation of the above would suggest that Clang has a bug.

However, as core issue 1852 specifies the above contradict with § 8.3.5/2 Functions [dcl.fct] and should be altered. The status of the issue is ready which suggests that the the changes have been accepted.

As such, the GCC has a bug that should be reported.