编译器不能推断出返回类型?

时间:2018-03-13 22:59:09

标签: c++ c++14 auto decltype

我正在尝试在自动功能上使用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'

为什么编译器还没有推断出返回类型?

3 个答案:

答案 0 :(得分:13)

因为对于类定义,编译器将首先确定所有成员名称和类型。 完成后分析函数体。

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

在编译点确定

using type_t = decltype(foo());

函数foo()的正文尚未进行分析。

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

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

注意:

这种现象仅适用于上课。类外的以下代码将编译:

auto bar() { return 12; }

using t = decltype(bar());

答案 1 :(得分:4)

这是因为类或结构中的using看到声明而不是成员的定义。请参阅auto,但看不到return 12;

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

想象一下如下

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

答案 2 :(得分:2)

@liliscent已经解释了编译示例的阶段,但是这里还有一个额外的 reductio ad absurdum :在方法体中,您可以使用声明为的同一个类的标识符在方法之后,因为只在解析完整的类定义后才翻译正文。现在想象一下,在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的定义生效时未知,而是因为它的返回类型尚未推断出来。

现在,虽然你的例子在理论上是明确的,但是可能需要付出很多努力来提出允许你的例子的标准语言,同时又足够窄以禁止我的两个例子。然后再次,这种好处充其量只是微不足道。