The Vee The Vee - 3 years ago 151
C++ Question

Clash between trailing return type and return type deduction

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()
?

Answer Source

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download