尾随返回类型不是类的完整类上下文的事实并不能解释为什么这个问题中的代码不能编译,尽管它解释了对另一个问题的答案中给出的代码的拒绝,特别是涉及的成员函数的代码的一部分qux
,并baz
如由OP说明。
请注意,@ NathanOliver 下面的注释基于以下猜想:foo
下面的成员函数的内联定义只是语法糖。这需要从标准中的引用证明。我还没有找到。一旦产生了这个引用,我肯定会接受一个答案,认为代码没有编译,因为trailing-return-type不是类的完整类上下文。
struct Test {
auto foo() {}
auto bar() -> decltype(foo()) {}
};
prog.cc:3:32: error: use of 'auto Test::foo()' before deduction of 'auto'
3 | auto bar() -> decltype(foo()) {}
| ^
prog.cc:3:32: error: use of 'auto Test::foo()' before deduction of 'auto'
如果具有使用占位符类型的声明的返回类型的函数没有非丢弃的返回语句,则推断返回类型,就好像在函数体的右括号处没有操作数的return语句一样。[例如:
auto f() { } // OK, return type is void
auto* g() { } // error, cannot deduce auto* from void()
- 结束例子]
[dcl.type.auto.deduct] /(2.1):
A型
T
包含占位符类型,和相应的初始值设定e
,被确定如下: (2.1)对于在包含占位符类型的返回类型声明的函数中发生的非废弃返回语句,T
是声明的返回类型,并且e
是return语句的操作数。如果return语句没有操作数,那么e
是void()
; (2.2)对于使用包含占位符类型的类型声明的变量,T是变量的声明类型,e是初始值设定项。如果初始化是直接列表初始化,则初始化器应该是一个braced-init-list,只包含一个赋值表达式,e是赋值表达式; (2.3)对于使用包含占位符类型的类型声明的非类型模板参数,T是非类型模板参数的声明类型,e是相应的模板参数。
根据[dcl.spec.auto] / 9和[dcl.type.auto.deduct] /(2.1),代码应该编译。但GCC和支持者拒绝了它。我遗漏了什么?
发布于 2019-02-22 11:13:26
struct Test { auto foo() { /*1*/ } auto bar() -> decltype(foo()) {} };
在标记1处,名称Test::bar
与范围内的所有其他成员一起在范围内struct Test
。因此,foo()
在类完成之前,编译器无法计算主体。
然后我们有一个部分订购:
Test::foo()
在推断其返回类型之前解析主体Test
在解析body之前完成类Test::foo()
Test::bar()
在完成课程之前分析尾随返回类型Test
(从您提出的问题不是欺骗)并且通过传递性,Test::bar()
必须在没有执行返回类型推导的情况下分析返回类型Test::foo()
。
由于要求提供标准报价,因此它来自[class.mem]
:
}
在类说明符结束时,类被视为完全定义的对象类型(或完整类型)。在类成员规范中,该类在函数体,默认参数,noexcept-specifiers和默认成员初始化器(包括嵌套类中的这类事物)中被视为完整。否则,它在其自己的类成员规范中被视为不完整。
https://stackoverflow.com/questions/-100008966
复制相似问题