考虑以下代码:

#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.data]:

静态数据成员定义中的初始化表达式属于其类的范围 .

§5.1.2/ 2&3 Lambda表达式[expr.prim.lambda]:

2 lambda表达式的求值导致prvalue临时(12.2) . 这个临时对象称为闭包对象 . lambda表达式不应出现在未评估的操作数中(第5条) . [注意:闭包对象的行为类似于函数对象(20.9).- end note] 3 lambda表达式的类型(也是闭包对象的类型)是一个唯一的,未命名的非联盟类类型 - 称为闭包type - 其属性如下所述 . 此类类型不是聚合(8.5.1) . 闭包类型在包含相应lambda表达式的最小块作用域,类作用域或命名空间作用域中声明 .

我们最终得出结论:表达式中的lambda:

int const foo::i = [&] { return foo().var; }();

可以正确访问 class fooprivate 成员,因为它是在 static 成员 iclass foo 的初始化表达式中声明和定义的,因此其范围是 class foo 的范围 .

代码在GCC v4.8Clang v3.4中编译并运行良好,但是它无法在VC 2013中编译,从而产生编译器错误:

错误C2248:'foo :: var':无法访问类'foo'中声明的私有成员

Question:

  • 上面记录的VC 2013的行为是一个错误,还是属于特定的VC 2013行为,可以通过更改特定的编译器设置来改变?