[英]Is getting the decltype of a deduced member function inside the trailing return type of another member function well-formed?
无论谁说这个问题都是一个问题的重复“ 是否有一个特定的原因,为什么一个尾随返回类型不是一个完整的类的背景? ”并不知道他/她在说什么。 尾随返回类型不是类的完整类上下文的事实并不能解释为什么这个问题中的代码不能编译,尽管它解释了对另一个问题的答案中给出的代码的拒绝,特别是如OP所解释的,涉及成员函数qux
和baz
的代码的一部分。
为了澄清我的论点,即下面的代码是有效的,你必须考虑[expr.prim.this]中的第二个注释 ,它说: 在trailing-return-type中,被定义的类不需要是完成以便访问类成员。 稍后声明的类成员不可见。 由于foo
在我的示例中在bar
之前声明,因此没有什么可以阻止编译器在trailing-return-type bar
访问foo
。
请注意@AathanOliver
下面的注释是基于下面的成员函数
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) :
包含占位符类型的类型
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和支持者拒绝了它。 我错过了什么?
struct Test { auto foo() { /*1*/ } auto bar() -> decltype(foo()) {} };
在标记1处,名称Test::bar
与struct Test
所有其他成员一起在范围内。 因此,在类完成之前,编译器无法分析foo()
的主体。
然后我们有一个部分订购:
Test::foo()
主体 Test::foo()
主体之前完成类Test
Test
之前分析尾随返回类型的Test::bar()
(从您提出的问题不是欺骗) 并且通过传递性,必须在不对Test::foo()
执行返回类型推导的情况下分析Test::bar()
返回类型。
由于要求标准报价,所以它来自[class.mem]
:
一类被认为是在闭合完全定义的对象类型(或完整的类型)
}
的类指定符 。 在类成员规范中 , 该类在函数体 ,默认参数, noexcept-specifiers和默认成员初始化器(包括嵌套类中的这类事物)中被视为完整 。 否则,它在其自己的类成员规范中被视为不完整。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.