简体   繁体   English

必须在C ++中用lambda捕获constexpr表达式吗?

[英]Must constexpr expressions be captured by a lambda in C++?

Here is a piece of code that won't compile in MSVC 2015 (ignore the uninitialized value access): 这是一段无法在MSVC 2015中编译的代码(忽略未初始化的值访问):

#include <array>
int main() {
    constexpr int x = 5;
    auto func = []() {
        std::array<int, x> arr;
        return arr[0];
    };
    func();
}

It complains that: 它抱怨说:

'x' cannot be implicitly captured because no default capture mode has been specified

But x is a constexpr ! 但是x是一个constexpr x is known at compile time to be 5 . x在编译时已知为5 Why does MSVC kick up a fuss about this? 为什么MSVC会对此大做文章? (Is it yet another MSVC bug?) GCC will happily compile it. (它是另一个 MSVC的错误?)GCC将愉快地编译它。

The code is well-formed. 代码格式正确。 The rule from [expr.prim.lambda] is: [expr.prim.lambda]的规则是:

If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (3.2) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression . 如果lambda表达式或函数的实例化调用泛型lambda odr的操作符模板 - 使用(3.2) this变量或具有自其存储持续时间的变量,则该实体应由lambda表达式捕获。

Any variable that is odr-used must be captured. 必须捕获任何使用odr的变量。 Is x odr-used in the lambda-expression? 在lambda表达式中使用x odr吗? No, it is not. 不它不是。 The rule from [basic.def.odr] is: [basic.def.odr]的规则是:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e , where either the lvalue-to-rvalue conversion (4.1) is applied to e , or e is a discarded-value expression (Clause 5). 变量x为潜在评估表达式出现的名字ex被ODR-使用ex ,除非施加左值到右值转换(4.1)到x产生一个常量表达式(5.20),其不调用任何非平凡的功能和,如果x是一个对象,则ex是表达式e的潜在结果集的一个元素,其中左值到右值的转换(4.1)应用于e ,或者e是丢弃值表达式(第5条) )。

x is only used in a context where we apply the lvalue-to-rvalue conversion and end up with a constant expression, so it is not odr-used, so we do not need to capture it. x仅用于我们应用左值到右值转换并最终得到常量表达式的上下文中,因此它不会被使用,因此我们不需要捕获它。 The program is fine. 该计划很好。 This is the same idea as why this example from the standard is well-formed: 这与为什么标准中的这个例子格式正确的想法是一样的:

 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 }; // ... } 

Even though x is a constexpr , it is no different from any other object, otherwise, and follows the same rules with regards to scoping. 尽管xconstexpr ,但它与任何其他对象没有区别,否则,遵循与范围有关的相同规则。 There are no exceptions to scoping rules for constexpr s, and a lambda must be coded to explicitly capture it. constexpr的范围规则没有例外,必须对lambda进行编码以明确捕获它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM