Lambda正在捕获constexpr对象
Lambda capturing constexpr object
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暗示了我的解释是正确的。
有没有明确说明引用捕获是指封闭范围中的对象还是引用?
std::integral_constant< int, i >
的第二个模板参数用于非类型形式的模版参数,特别是积分或枚举类型(14.3.2p1项目符号1),因此必须是int
类型的转换常量表达式。
在lambda表达式中,当在复合语句(5.1.2p11)中使用实体odr时,会发生隐式捕获;在显式模板实例化中使用转换后的常量表达式不是odr使用(3.2p3),因此第一个示例是有效的。
在第二个例子中,我认为gcc拒绝它是不正确的;5.1.2p17在注释中表示:
不是odr使用的id表达式引用原始实体,而不是闭包类型的成员。
尽管整个段落都在讨论通过复制捕获,但没有理由不将此规则应用于通过引用捕获。毫不奇怪,标准对此并不明确;实际上没有理由捕获一个可以通过引用在转换的常量表达式中使用的实体。
首先,我可以用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
不是"积分常数"。
- Constexpr替代了新的放置方式,可以让内存中的对象保持未初始化状态
- 为什么我的 constexpr 对象在我的函数中不是 constexpr?
- 编译时生成应在构造函数中创建的非 constexpr 对象数组
- 为什么带有指针子对象的文字类类型的 constexpr 表达式不能是非类型模板参数
- 我可以制作一个std::set的constexpr对象吗
- 类本身内部的类对象的静态constexpr数组
- 使用 constexpr 初始化 std.array 中的对象
- l值引用对象上的Constexpr成员函数:Clang和gcc不同意
- constexpr函数可以返回本地对象的指针吗?
- 从“if constexpr”分支扩展对象生存期/范围
- 如果我的班级是字面的班级,那么将我的类的对象声明为constexpr是多余的
- static_assert HANA 教程中的非constexpr对象
- 有没有办法根据运行时值的类型返回 constexpr 对象
- constexpr引用非const对象
- 从 constexpr 返回对象?
- 使用方法失败更改constexpr对象成员
- Lambda正在捕获constexpr对象
- 对于潜在的constexpr对象,所有比较运算符都是constexpr
- 使用移动 CTOR 的 constexpr 对象的 constexpr 数组
- 传递 constexpr 对象