使用lambda捕获的constexpr值作为数组维度

Ser*_* K. 5 arrays lambda constexpr c++11 c++14

GCCClang编译以下代码:

void Test()
{
   constexpr int Size = 3;
   auto Lambda = [Size]{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)

但是,VisualStudio 2015 CTP 6没有.尽管如此,所有3个编译器都对此代码感到满意:

void Test()
{
   static constexpr int Size = 3;
   auto Lambda = []{ int Dim[Size]; };
}
Run Code Online (Sandbox Code Playgroud)

哪个片段实际上是以正确的方式进行的?C++标准说什么?

这个问题与Lambda捕获constexpr对象有关

dyp*_*dyp 6

C++ 11 [expr.prim.lambda]/12

如果lambda表达式odr-使用此变量或具有自其到达范围的自动存储持续时间的变量,则该实体应由lambda表达式捕获.

和/ 17

每个id-expression是由副本捕获的实体的odr使用,它被转换为对闭包类型的相应未命名数据成员的访问.[ 注意:不是odr-use 的id表达式是指原始实体,永远不是闭包类型的成员.[...] - 结束说明 ]

所以我们甚至不需要Size在第一个例子中捕获(在它不是的情况下static),因为从该变量读取不是odr-use,因为它可以出现在常量表达式中并且立即应用左值到右值的转换对它,[basic.def.odr]/2

名称显示为潜在评估表达式的变量是odr-used,除非它是满足出现在常量表达式中的要求的对象,并且立即应用左值到右值转换.

(但我不清楚数组边界是否需要进行ltr转换.)

Size通过引用捕获,或者Size显式捕获(通过复制)但不使用odr 时,同样适用:在lambda中使用id-expression Size访问constexpr声明的变量Test,而不是任何捕获的成员(用于逐个捕获) :IFF访问不构成odr使用).

C++ 14 [expr.prim.lamda]/12为这里不相关的多态lambda添加了一些措辞,并将/ 17移动到/ 18.使用odr的规则更复杂,但我认为这不是因为相同的潜在原因(读取编译时常量)而使用的.