为什么静态初始值设定项中的 lambda 无法访问 VC++2013 中类的私有成员?
Why lambda in static initializer can't access private members of class in VC++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;
}
考虑标准§9.4.2/2静态数据成员[class.static.]数据:
static
数据成员的定义在其类的作用域中。
和
§5.1.2/2& 3 Lambda表达式[expr.prim.lambda]:
2
lambda表达式的求值结果是一个右值临时值(12.2)。这个临时对象称为闭包对象。lambda表达式不能出现在未求值的操作数中(第5条)。[注:闭包对象的行为类似于函数对象(第20.9条)。]端注)
3
lambda表达式的类型(也是闭包对象的类型)是唯一的,未命名的非联合类类型-称为闭包类型-其属性如下所述。这个类类型不是聚合(8.5.1)。闭包类型在包含相应lambda表达式的最小块作用域、类作用域或命名空间作用域中声明。
我们最终得出结论,表达式中的lambda:
int const foo::i = [&] { return foo().var; }();
可以正确访问class foo
的private
成员,因为它是在class foo
的static
成员i
的初始化表达式中声明和定义的,因此它的作用域是class foo
的作用域。
代码在GCC v4.8和Clang v3.4中编译和运行良好。,但是它无法在vc++ 2013中编译,产生编译错误:
错误C2248: 'foo::var':无法访问在类'foo'中声明的私有成员
问题:
- 以上记录的vc++ 2013的行为是一个bug,或者它是属性到特定的vc++ 2013行为,可以通过改变特定的编译器设置来改变?
这是Visual Studio在2017年之前的一个bug,在Visual Studio 2019中修复。演示:https://gcc.godbolt.org/z/4564EKbEr
至于
int const foo::i = [&] { return foo().var; }();
非局部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;
}
演示:https://gcc.godbolt.org/z/oPscPo1eG
在Visual Studio 2022版本17.2中修复。见https://developercommunity.visualstudio.com/t/Templated-static-initializer-cannot-acce/1620389
- 如果使用低于 VS2015 的 vc++ 编译器版本编译,则 DLL 中的访问冲突
- vc++ 访问冲突读取位置
- 我如何克服无声无法更改VC 2013中的路径环境变量
- 我们如何使用Visual Studio 2013访问C 中的更改编号
- 如何为 VC++ 2013 安装平台工具集
- 在 VC++ 中访问一个文件中声明的变量.(外部关键字用法)
- 在我的发布应用程序 (VC++ 2013) 中摆脱 msvcr120.dll/msvcp120.dll依赖项
- 视觉 我们可以在C++/ VC++中访问ODB++文件(PCB)
- 为什么 VC++ 2013 不支持承诺的非静态数据成员初始值设定项
- 如何在VC++ 2013中使用最小GC
- matlab R2013a与MS VC++2013之间的链接错误
- 在MS VC 2013 Express中将C++dll从32位转换为64位
- 为什么VC++2013拒绝编译嵌套类型,当用作模板函数返回类型时,用using关键字使其可见
- VC++2013 中嵌套可变参数模板化结构的别名
- vc++ 2013调试和发布版本
- cpcms你好世界应用程序与MS vc 2013 Express
- LNK2038 error VC++ 2013
- 为什么静态初始值设定项中的 lambda 无法访问 VC++2013 中类的私有成员?
- 为什么成员函数尝试块处理程序中的 lambda(捕获"this")无法访问 VC++ 2013 中的私有数据成员?
- 用VC 2013编译Protobufs和Libyara