【问题标题】:Compiler can't deduce the return type?编译器无法推断返回类型?
【发布时间】:2018-08-22 08:39:54
【问题描述】:
我正在尝试在自动功能上使用 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'
为什么编译器还没有推导出返回类型?
【问题讨论】:
标签:
c++
c++14
auto
decltype
【解决方案1】:
因为对于类的定义,编译器会首先确定所有的成员名称和类型。 在完成后分析函数体。
这就是为什么一个类的成员函数可以调用在它自己的定义之后声明的另一个成员函数。
此时编译正在确定
using type_t = decltype(foo());
函数foo()的主体尚未分析。
作为补救措施,您可以使用
static auto foo() -> decltype(12) {
return 12;
}
注意:
此现象仅适用于班级。类外的以下代码将编译:
auto bar() { return 12; }
using t = decltype(bar());
【解决方案2】:
这是因为类或结构中的using 看到声明但看不到成员的定义。所以看到auto,但没有看到return 12;。
如果不同,会很危险,因为成员的定义可以使用已定义的(using 或typedef)类型。
想象一下如下
struct Thing {
static auto foo() {
return type_t{};
}
using type_t =
decltype(foo());
};
【解决方案3】:
@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(); }
};
这失败了,不是因为bar 在foo 的定义生效时是未知的,而是因为它的返回类型还没有被推导出来。
现在,虽然您的示例在理论上是明确的,但可能需要付出很多努力才能提出标准语言,以允许您的示例同时又足够狭窄以禁止我的两个示例。再说一次,好处似乎充其量是微不足道的。