101*_*010 5 c++ lambda visual-c++ c++11 visual-studio-2013
考虑以下代码:
#include <iostream>
class foo {
int var = 99;
public:
static int const i;
};
int const foo::i = [&] { return foo().var; }();
auto main() -> int {
std::cout << foo::i << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
考虑标准§9.4.2/ 2静态数据成员[class.static.data]:
static数据成员定义中的初始化表达式属于其类的范围.
和
§5.1.2/ 2&3 Lambda表达式[expr.prim.lambda]:
2lambda表达式的评估导致prvalue临时(12.2).这个临时对象称为闭包对象.lambda表达式不应出现在未评估的操作数中(第5条).[注意:闭包对象的行为类似于函数对象(20.9).-结束注释]
3lambda-expression的类型(也是闭包对象的类型)是一个唯一的,未命名的nonunion类类型 - 称为闭包类型 - 其属性如下所述.此类类型不是聚合(8.5.1).闭包类型在包含相应lambda表达式的最小块作用域,类作用域或命名空间作用域中声明.
我们最终得出结论:表达式中的lambda:
int const foo::i = [&] { return foo().var; }();
Run Code Online (Sandbox Code Playgroud)
可以正确地访问private成员,class foo因为它是在static成员的初始化表达式中声明和定义i的class foo,因此其范围是其范围class foo.
代码在GCC v4.8和Clang v3.4中编译并运行良好,但它无法在VC++ 2013中编译产生编译器错误:
错误C2248:'foo :: var':无法访问类'foo'中声明的私有成员
题:
这是 Visual Studios 2017 年之前的一个错误,在 Visual Studio 2019 中已修复。演示: https: //gcc.godbolt.org/z/4564EKbEr
至于
int const foo::i = [&] { return foo().var; }();
Run Code Online (Sandbox Code Playgroud)
非本地 lambda 表达式不能有捕获默认值,因此我在演示中更改了它。
但正如我的同事指出的那样,Visual Studio 2019 中的成员模板仍然存在类似的错误:
#include <iostream>
class foo {
int var = 99;
public:
template<class>
static int const i;
};
template<class>
int const foo::i = [] { return foo().var; }(); // fails in MSVC
auto main() -> int {
std::cout << foo::i<int> << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/oPscPo1eG
它已在 Visual Studio 2022 版本 17.2 中修复。请参阅https://developercommunity.visualstudio.com/t/Templated-static-initializer-cannot-acce/1620389
| 归档时间: |
|
| 查看次数: |
438 次 |
| 最近记录: |