如何从 lambda-functor 的主体中递增变量?

How to increment a variable from lambda-functor's body?

本文关键字:变量 主体 lambda-functor      更新时间:2023-10-16

我试图从lambda表达式中增加一个局部变量:

#include <iostream>
template<typename T>
T foo(T t){
    T temp{};
    [temp]() -> void { 
        temp++; 
    }();
    return temp;
}
int main()
{
    std::cout<< foo(10) << std::endl;
}

演示

但是得到了以下错误:

main.cpp: In instantiation of 'foo(T)::<lambda()> [with T = int]':
main.cpp:6:6:   required from 'struct foo(T) [with T = int]::<lambda()>'
main.cpp:8:6:   required from 'T foo(T) [with T = int]'
main.cpp:14:23:   required from here
main.cpp:7:13: error: increment of read-only variable 'temp'
         temp++; 
             ^

在c++11/14中是否有一些变通方法?

temp在不可变lambda中通过复制捕获时无法修改。

您可以通过引用捕获temp

template<typename T>
T foo(T t){
    T temp{};
    [&temp]() -> void { 
        temp++; 
    }();
    return temp;
}

如果要通过值捕获变量并对其进行修改,则需要标记lambda mutable:

[temp]() mutable -> void {
//       ^^^^^^^ 
    temp++; 
}();

这允许主体修改由值捕获的参数,并调用它们的非常量成员函数

它是C++14,因此您可以简化lambda
也就是说,这些是一些有效的解决方案(我假设你想改变原始变量的值,而不是它的副本):

  • 参考捕获:

    [&temp]() { temp++; }();

(您必须保证temp的寿命是lambda 的寿命之一

  • 来回复制:

    temp = [temp = temp]() mutable { return ++temp; }();

(您不需要保证temp的寿命是lambda的寿命)

  • 来回移动:

    temp = [temp{std::move(temp)}]() mutable { temp++; return std::move(temp); }();

(您不需要保证temp的寿命是lambda的寿命)

等等…

您所说的"局部变量"有点模棱两可。

  1. 要增加footemp,您需要通过引用捕获,因此您的lambda看起来像:[&temp] { temp++; }
  2. 要增加lambda的temp,您需要使用mutable关键字,因此您的lambda看起来像:[temp]() mutable { temp++; }

您似乎不太可能尝试执行2,因为您所做的任何更改都将在lambda返回时丢失,因为它不会返回任何内容。并且,在您给出的示例中,您没有在lambda中进一步使用temp

因此,假设您正在尝试执行1,则需要确保T不是引用,而不是const。以下任何一个例子都会给你带来麻烦:

const auto t = 1;
foo(t);

auto& t = bar;
foo(t);

为了避免这两种情况,您应该用decay_t:定义footemp

decay_t<T> temp{};