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

时间:2015-02-27 10:54:40

标签: arrays c++11 lambda c++14 constexpr

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

有关

1 个答案:

答案 0 :(得分:6)

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

  

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

和/ 17

  

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

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

  

其名称显示为可能已评估的表达式的变量是odr-used,除非它是满足出现在常量表达式和左值到右值的要求的对象   立即转换。

(但我不清楚阵列边界是否需要进行l-t-r转换。)

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

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