Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 534
The Vee Avatar asked Sep 29 '17 18:09

The Vee


People also ask

Why use trailing return type?

The trailing return type feature removes a C++ limitation where the return type of a function template cannot be generalized if the return type depends on the types of the function arguments.

Can return type be auto?

In C++14, you can just use auto as a return type.

What does Decltype auto do?

Use auto and decltype to declare a function template whose return type depends on the types of its template arguments. Or, use auto and decltype to declare a function template that wraps a call to another function, and then returns the return type of the wrapped function.

Can auto be a reference?

Like pointers, we can also use auto to declare references to other variables.


1 Answers

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

like image 147
NathanOliver Avatar answered Sep 30 '22 07:09

NathanOliver