[英]Difference between ref-captured and non-explicitly captured constexpr variables in lambda-expressions
[英]Must constexpr expressions be captured by a lambda in C++?
这是一段无法在MSVC 2015中编译的代码(忽略未初始化的值访问):
#include <array>
int main() {
constexpr int x = 5;
auto func = []() {
std::array<int, x> arr;
return arr[0];
};
func();
}
它抱怨说:
'x' cannot be implicitly captured because no default capture mode has been specified
但是x
是一个constexpr
! x
在编译时已知为5
。 为什么MSVC会对此大做文章? (它是另一个 MSVC的错误?)GCC将愉快地编译它。
代码格式正确。 [expr.prim.lambda]的规则是:
如果lambda表达式或函数的实例化调用泛型lambda odr的操作符模板 - 使用(3.2)
this
变量或具有自其存储持续时间的变量,则该实体应由lambda表达式捕获。
必须捕获任何使用odr的变量。 在lambda表达式中使用x
odr吗? 不它不是。 [basic.def.odr]的规则是:
变量
x
为潜在评估表达式出现的名字ex
被ODR-使用ex
,除非施加左值到右值转换(4.1)到x
产生一个常量表达式(5.20),其不调用任何非平凡的功能和,如果x
是一个对象,则ex
是表达式e
的潜在结果集的一个元素,其中左值到右值的转换(4.1)应用于e
,或者e
是丢弃值表达式(第5条) )。
x
仅用于我们应用左值到右值转换并最终得到常量表达式的上下文中,因此它不会被使用,因此我们不需要捕获它。 该计划很好。 这与为什么标准中的这个例子格式正确的想法是一样的:
void f(int, const int (&)[2] = {}) { } // #1 void f(const int&, const int (&)[1]) { } // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; // ... }
尽管x
是constexpr
,但它与任何其他对象没有区别,否则,遵循与范围有关的相同规则。 constexpr
的范围规则没有例外,必须对lambda进行编码以明确捕获它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.