我今天尝试做类似的事情。我很惊讶它没有编译。
struct Test {
// v----- Remove me to compile
// /*
static constexpr auto get_test1 = [](Test const& self) {
return self.test; // error, Test is incomplete
};
// */
// Handwritten version of the lambda
struct {
constexpr auto operator() (Test const& self) const {
return self.test; // ok
}
}
static constexpr get_test2{};
int test;
};
它表示Test
类型在范围内不完整。然而,lambda的手写版确实有效。这是什么技术原因?这是标准中的疏忽,还是有一个特定的措辞使Test
在lambda中不完整?
答案 0 :(得分:3)
这是我能找到的:
§5.1.2Lambda表达式[expr.prim.lambda]
[...] [注意:lambda声明符中引用的名称在lambda表达式出现的上下文中查找。 - 尾注]
- 醇>
lambda-expression的复合语句产生函数调用运算符的函数体(8.4),但出于名称查找的目的 (3.4),[...]复合陈述在上下文中考虑 lambda-expression。
如果我没有误读标准,这意味着在lambda的上下文中查看/考虑参数中的Test
和self
,这是类范围。 Test
不完整。
至于嵌套类允许的原因:
§9.2班级成员[class.mem]
- 在classspecifier的结束时,类被视为完全定义的对象类型(3.9)(或完整类型)。内 class member-specification,该类被认为是完整的 函数体,默认参数,引用的使用声明 继承构造函数(12.9),异常规范s和 用于非静态数据成员的brace-or-equal-initializer(包括 嵌套类中的这类东西)。否则它被认为是不完整的 在其自己的类成员规范中。
醇>
答案 1 :(得分:0)
我认为你的编译器是正确的。 Test
仍然不完整。在类定义结束之前,不会延迟处理这样的数据成员的初始化程序(这要求类型完成)。
我无法找到处理此问题的标准部分,但我记得它是作为C ++ 17草案的国家机构评论(US 24,P0488R0)而提出的:
当前规范禁止
constexpr static
数据成员与类型相同 附上课。示例:
struct A { int val; static constexpr A cst = { 42 }; // error };
显然,完全解除限制可能会导致一些重大变化,因此评论并没有增加共识"。