I'm writing some code where the return type of a function is rather complicated. I'd like to make use of auto
for deducing from the return type, but that's obviously not possible in a forward declaration. So I was hoping to at least only duplicate the contents of the return statement and do the following,
int q = 5; // veeery complicated type
/* Declaration - the best we can do */
auto f() -> decltype(q);
/* Later, in a different file */
auto f() {
return q;
}
This produces the following error in GCC 7,
error: ambiguating new declaration of ‘auto f()’
note: old declaration ‘int f()’
Of course I could repeat
auto f() -> decltype(q) {
return q;
}
in the definition (which works) but why should I need to when the return type is already uniquely given by the return
statement? How is the type of f
in my definition ultimately any more ambiguous than int f()
?
The problem here is that a trailing return is not the same as purely deduced return type. In [dcl.spec.auto]/2
[...]If the function declarator includes a trailing-return-type (8.3.5), that specifies the declared return type of the function
So
auto f() -> decltype(q);
is really
int f();
which is different from
auto f()
There is also [dcl.spec.auto]/13
Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type. [ Example:
auto f(); auto f() { return 42; } // return type is int auto f(); // OK int f(); // error, cannot be overloaded with auto f() decltype(auto) f(); // error, auto and decltype(auto) don’t match
Which is kind of opposite of what is going on here but it does further exemplify that this is not allowed