编译器无法推断出 return 类型?

Compiler can't deduce the return type?

我正在尝试在自动功能上使用 decltype 关键字:

struct Thing {
   static auto foo() {
     return 12;
   }
   using type_t =
       decltype(foo());
};

我收到以下错误 (gcc 7.4):

<source>:6:25: error: use of 'static auto Thing::foo()' before deduction of 'auto'
            decltype(foo());
                         ^
<source>:6:25: error: use of 'static auto Thing::foo()' before deduction of 'auto'

为什么编译器还没有推导出 return 类型?

这是因为 class 或结构中的 using 看到的是声明而不是成员的定义。所以看到 auto 但没有看到 return 12;.

如果不同,会很危险,因为成员的定义可以使用已定义的(usingtypedef)类型。

设想如下

struct Thing {
   static auto foo() {
     return type_t{};
   }
   using type_t =
       decltype(foo());
};

因为对于class的定义,编译器会先判断所有的成员名称和类型。完成后分析函数体

这就是为什么 class 成员函数可以调用在它自己的定义之后声明的另一个成员函数。

此时编译正在确定

using type_t = decltype(foo());

函数 foo() 的主体尚未分析。

作为补救措施,您可以使用

static auto foo() -> decltype(12) {
  return 12;
}

注意:

此现象仅适用于class。 class 之外的以下代码将编译:

auto bar() { return 12; }

using t = decltype(bar());

@liliscent 已经解释了编译示例的阶段,但这里还有一个额外的 reductio ad absurdum:在方法主体中,您可以使用来自相同 class 是在 之后 方法声明的,因为正文仅在解析完整的 class 定义后才被翻译。现在想象一下,foo 的推导类型在 Thing 的定义中可用。那么我们应该可以合法的写出如下内容:

struct Thing {
    static auto foo() {
      return type_t{};
    }
    using type_t =
        decltype(foo());
};

现在 type_t 应该是什么?同样,不允许以下内容:

struct Thing {
    static auto foo() { return bar(); }
    static auto bar() { return foo(); }
};

这失败了,不是因为 barfoo 的定义生效时未知,而是因为它的 return 类型还没有推导出来。

现在,虽然您的示例在理论上是明确的,但可能需要付出很多努力才能提出允许您的示例同时足够狭窄以禁止我的两个示例的标准语言。再一次,好处似乎充其量是微不足道的。