gpt4 book ai didi

c++ - 带有空捕获的 Lambda 表达式

转载 作者:IT老高 更新时间:2023-10-28 22:20:50 26 4
gpt4 key购买 nike

我在使用 lambdas 时遇到了一个有趣的案例(至少对我而言),我想知道这是编译器错误还是标准功能允许的问题。

让我们切入正题。有示例代码:

const int controlValue = 5;
std::vector<int> vect{ 0, 1, 2, 3 };
const auto result = std::any_of(vect.begin(), vect.end(), [](const int& item)
{
return item == controlValue;
});

注意 controlValue 变量没有被 lambda 表达式捕获。此外,在 cppreference对于 lambda 表达式,声明 [] - 不捕获任何内容

使用 VS2015 编译上述代码会出现错误,这并不奇怪:

error C3493: 'controlValue' cannot be implicitly captured because no default capture mode has been specified

但是,当将 MinGWgcc 4.8.2 一起使用时,相同的示例可以编译并运行。一些在线编译器,包括 gcc 5.4.0clang 3.8.0 给出了类似的结果。

controlValue 丢失它的 const 时,所有经过测试的编译器都会给出所有预期的错误(变量未被捕获,这很好)。

在这种情况下,哪些编译器符合标准?这是否意味着这里对 const 变量使用了一些优化或其他“技巧”?也许某些东西被隐含地捕获了?谁能解释一下这里发生的情况?

编辑:

有人指出此问题与 Lambda capturing constexpr object 重复。 .虽然答案可能有些相关(指向 odr 用例),但问题是在通过 ref 捕获时发生错误。这里的主题完全不同,重点在于根本不显式捕获变量(尽管在 lambda 主体中使用它)。

在查看了更多与 lambda 相关的问题后,如果有人感兴趣,我会指向 Using lambda captured constexpr value as an array dimension这(与@Barry 所述相同)暗示了 VS2015 错误,并显示将此处示例中的 controlValue 变量设置为 static 修复了 VS2015 下的编译。

最佳答案

这是一个 VS 错误。代码格式完美。

[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.

如果根据 [basic.def.odr],使用 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).

并且,来自 [expr.const]:

A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions: [...] an lvalue-to-rvalue conversion (4.1) unless it is applied to a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile const object with a preceding initialization, initialized with a constant expression

在:

return item == controlValue;

controlValue 是一个整数类型的左值,它指的是一个用常量表达式初始化的完整的非 volatile const 对象。因此,当我们在涉及左值到右值转换的上下文中使用 controlValue 时,它不是 odr 使用的。因为它不是 odr-used,所以我们不需要捕获它。

当您将 controlValue 更改为 non-const 时,它不再是常量表达式,并且相等性检查 odr-使用它.由于它没有被捕获但被 odr 使用,因此 lambda 格式不正确。


请注意,标准中恰好出现了这样的示例:

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

// ...
}

关于c++ - 带有空捕获的 Lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43119643/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com