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

Using lambda captured constexpr value as an array dimension

GCCClang 编译以下代码:

void Test()
{
   constexpr int Size = 3;
   auto Lambda = [Size]{ int Dim[Size]; };
}

然而,VisualStudio 2015 CTP 6 没有。尽管如此,所有 3 个编译器都对这段代码感到满意:

void Test()
{
   static constexpr int Size = 3;
   auto Lambda = []{ int Dim[Size]; };
}

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

此问题与Lambda capturing constexpr object

相关

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

If a lambda-expression odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.

和/17

Every id-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [ Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. [...] — end note ]

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

A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied.

(我不清楚数组边界是否需要 l-t-r 转换。)

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

C++14 [expr.prim.lamda]/12 添加了一些与这里无关的多态 lambda 的措辞,并将 /17 移动到 /18。 odr-use 的规则更复杂,但我认为出于相同的根本原因(读取编译时常量),它不是 odr-use。