如何使可变 lambda 捕获列表的一些成员成为 const?

How to make const some members of a mutable lambda capture list?

提问人:Constructor 提问时间:12/30/2018 更新时间:12/30/2018 访问量:267

问:

mutableLambda 可以更改其捕获列表成员的值(按值捕获的值)。有没有办法让捕获列表的某些成员保留在 lambda 中?constmutable

例如,我想更改,但在以下代码示例的正文中:iconstjlambda

#include <iostream>

int main()
{
    int i = 42;
    int j = 108;
    auto lambda = [i, j]() mutable
    {
        i = 15;
        std::cout << "i = " << i << std::endl;
        std::cout << "j = " << j << std::endl;
    };

    lambda();
}
C++(英语:C++) λ 常数 可变 常量正确性

评论

3赞 Passer By 12/30/2018
是的。编写结构体。
1赞 Sam Varshavchik 12/30/2018
您始终可以捕获具有成员的类:。现在在可变 lambda 中按值捕获它,并且仍然是 。conststruct hasI { const int i; }hasI.iconst
0赞 Constructor 12/30/2018
@SamVarshavchik 嗯,有趣的解决方案。我可以使这个结构体本地化且未命名,因此这里不会有很多样板。你能写下你的评论作为答案吗?
0赞 Constructor 12/30/2018
@PasserBy 谢谢。

答:

2赞 Kerrek SB 12/30/2018 #1

由于简单捕获具有它们捕获的事物的精确、cv 限定类型,因此您可以创建外部变量,从而获得常量捕获:const

#include <iostream>

int main()
{
    const int i = 42;
//  ^^^^^

    int j = 108;
    auto lambda = [i, j]() mutable
    {
        i = 15;
        std::cout << "i = " << i << std::endl;
        std::cout << "j = " << j << std::endl;
    };

    lambda();
}

当然,如果你需要在某个时候修改外部变量,你需要先复制它——或者以某种方式重构你的代码,让它更整洁一些。

评论

0赞 Constructor 12/30/2018
谢谢。是的,我可能想修改它。
1赞 StoryTeller - Unslander Monica 12/30/2018
真的不是复制初始化吗?因此,不应进行 cv 限定符。
0赞 Kerrek SB 12/30/2018
@StoryTeller:你告诉我,你指的是哪条规则让你相信这一点?
1赞 StoryTeller - Unslander Monica 12/30/2018
好吧,在 中,我们不会在 中得到一个常量对象。如果我们要使用 init-list 也不会是 const,可以很容易地尝试。我怀疑你得到的错误是因为实际上没有被捕获。它是一个常量表达式(你可以用它来定义一个数组)。auto k = i;ki = as_const(i)ii
1赞 Kerrek SB 12/30/2018
@StoryTeller:从 [expr.prim.lambda.capture] 中,将第 4 段(用于 simple-capture 指定的实体)和第 10 段(用于“此类数据成员的类型是 [...]相应捕获实体的类型“。(eel.is/c++draft/expr.prim.lambda.capture#10)所以需要明确的是,是的,捕获和 .[x][x = x]