尾随 return 类型和 return 类型推导之间的冲突

Clash between trailing return type and return type deduction

我正在编写一些代码,其中 return 类型的函数相当复杂。我想利用 auto 从 return 类型推导,但这在前向声明中显然是不可能的。所以我希望至少只复制 return 语句的内容并执行以下操作,

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;
}

这会在 GCC 7 中产生以下错误,

error: ambiguating new declaration of ‘auto f()’
note: old declaration ‘int f()’

我当然可以重复

auto f() -> decltype(q) {
  return q;
}

在定义中(有效)但是当 return 类型已经由 return 语句唯一给出时,为什么我还需要这样做?在我的定义中 f 的类型最终如何比 int f() 更模棱两可?

这里的问题是尾随 return 与纯粹推导的 return 类型不同。在 [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

所以

auto f() -> decltype(q);

真的

int f();

不同于

auto f()

还有[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

这与这里发生的事情有点相反,但它确实进一步说明这是不允许的