Lambda捕获constexpr对象

时间:2012-11-20 08:13:57

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

GCC 4.7.2编译:

constexpr int i = 5;
[]{ std::integral_constant< int, i >(); }; // nonstandard: i not captured

但不是这样:

constexpr int i = 5;
[&i]{ std::integral_constant< int, i >(); }; // GCC says i not constexpr

根据C ++11§5.1.2/ 15:

,后一个例子对我来说是正确的
  

如果实体被隐式或显式捕获但未被副本捕获,则通过引用捕获该实体。未指定是否在闭包类型中为通过引用捕获的实体声明了其他未命名的非静态数据成员。

似乎lambda中捕获的对象i引用了封闭范围中的变量,即constexpr,而不仅仅是const引用。

标准明确指出,使用按值捕获转换为对lambda对象的相应成员的使用。我认为5.1.2提示我的解释是正确的。

是否有任何明确说明通过引用捕获是指引用范围内的对象还是引用?

2 个答案:

答案 0 :(得分:12)

std::integral_constant< int, i >的第二个模板参数用于非类型形式的模板参数,特别是< em>整数或枚举类型(14.3.2p1项目符号1)因此必须是int类型的转换常量表达式。

lambda-expression 中,当化合物语句中使用了一个实体时,会发生隐式捕获(5.1.2p11);在显式模板实例化中使用转换的常量表达式不是odr-use(3.2p3),因此第一个示例是有效的。

在第二个例子中,我认为gcc拒绝它是不正确的; 5.1.2p17在一份说明中说:

  

不是odr-use的 id-expression 是指原始实体,永远不是闭包类型的成员。

虽然整个段落是通过副本讨论捕获,但是没有理由不通过引用来应用此规则。毫不奇怪,标准尚不清楚;实际上没有理由捕获可以通过引用在转换的常量表达式中使用的实体。

答案 1 :(得分:0)

首先,我可以在Ubuntu 12.04上用gcc 4.6.3和clang 3.0确认你的观察结果。

我没有C ++ 11标准(只有草稿),所以我不能对此发表评论。但从我的理解,看看等效陈述

constexpr int i = 5;
const int &j = i;
std::integral_constant<int, j>();

gcc和clang都没有编译,因为j不是“整数常量”。