Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ &引用;刷新“;lambda对象_C++_C++11_Lambda - Fatal编程技术网

C++ &引用;刷新“;lambda对象

C++ &引用;刷新“;lambda对象,c++,c++11,lambda,C++,C++11,Lambda,我创建了我的lambda,如下所示: int i = 0; auto gen_lam = [=]() mutable -> int {return ++i;}; 它有效地统计调用它的次数,因为它存储捕获的i。有没有办法“重建”对象,使其从初始值i开始 大致如下: decltype(gen_lam) gen_lam2; 这样,以下代码输出的是11,而不是12 std::cout << gen_lam() << std::endl; decltype(gen_la

我创建了我的lambda,如下所示:

int i = 0;
auto gen_lam = [=]() mutable -> int {return ++i;};
它有效地统计调用它的次数,因为它存储捕获的
i
。有没有办法“重建”对象,使其从初始值
i
开始

大致如下:

decltype(gen_lam) gen_lam2;
这样,以下代码输出的是
11
,而不是
12

std::cout << gen_lam() << std::endl;

decltype(gen_lam) gen_lam2;

std::cout << gen_lam2() << std::endl;

std::cout简单地完成,将lambda创建封装在lambda中,您可以在需要重新初始化内部lambda时调用该lambda:

auto wrap_lam = [](int i) {return [=]() mutable {return ++i;};}
auto gen_lam = wrap_lam(0);
auto gen_lam2 = wrap_lam(0);
或者,只要在需要时复制以保留状态:

auto gen_lam = [=]() mutable -> int {return ++i;};
const auto save = gen_lam;

如果您只需要完全重置,那么首先自然保存为const对象。

我不认为lambda捕获的初始值可以是其类型的一部分,因为这意味着每次代码运行时(可能使用不同的
I
)都必须在运行时生成一个新类型

我也不认为捕获的可变值的初始状态是存储的,因为这会占用额外的内存

总之,如果你只有一个lambda函数对象,它是按照你描述的方式创建的,我认为你没有任何方法可以重新创建它的原始状态


但是,如果您控制生成该函数对象的代码,则可以将其拉入函数,然后再次调用该函数。或者你可以手工创建一个函数对象类,正如@NeilKirk已经建议的那样。

我认为你想要的可以通过一个捕获不同计数器的生成器来实现

#include <iostream>
#include <functional>

using namespace std;

int main()
{
    int i = 0;
    int j = 0;

    auto lambda_generator = [](int& val) {
        auto var = [=]() mutable -> int {return ++val;};
        return var;
    };

    auto counter1 = lambda_generator(i);

    std::cout << counter1() << std::endl;

    auto counter2 = lambda_generator(j);

    std::cout << counter2() << std::endl;

}
#包括
#包括
使用名称空间std;
int main()
{
int i=0;
int j=0;
自动lambda_生成器=[](int&val){
自动变量=[=]()可变->int{return++val;};
收益var;
};
自动计数器1=lambda_发电机(i);

std::cout不能访问lambda内部复制的内部变量,但lambda本身可以

通过在调用上建立协议,您可以向lambda发送命令以改变其状态。例如:

auto counter = [](int i0){
    int i = i0;
    return [i0, i](bool reset=false) mutable {
        if (reset) {
            i = i0;
            return -1;
        } else {
            return ++i;
        }
    };
};
这里我使用了一个可选参数,当传递
true
时,它会将计数器重置为初始值

int main() {
    auto c = counter(10);
    std::cout << c() << "\n"; // 11
    std::cout << c() << "\n"; // 12
    std::cout << c() << "\n"; // 13
    c(true); // send reset message
    std::cout << c() << "\n"; // 11
    std::cout << c() << "\n"; // 12
    std::cout << c() << "\n"; // 13
}
intmain(){
自动c=计数器(10);

std::cout为了简单和理智,我会为此创建一个普通的旧函子类。你可以在
std::function
@402:这没有异议。你也不能从匿名名称空间命名类型。@402:啊,我理解你的错误。你不能
decltype([]{})lambda=[]{}因为这两个lambda具有不同的类型。不能命名这些类型的事实是不相关的。对于
decltype(1)foo=“one”,您有相同的两种类型问题;
@402第二个示例的共享状态让我很害怕。重复数据消除器的解决方案是每个lambda都有自己的状态,这要好得多。@SebastianRedl我同意……我甚至没有想过捕获复制的传递值整数。出于教学目的,我会在这里留下我蹩脚的答案。@MSalters我会完全删除第二个示例n甚至写
auto const prototype=[=]()可变{return++i;}
所以您知道原型本身并没有意外地增加。很好……我甚至没有想到在生成器中捕获传递值计数器。@MSalters:只是想指出,它可以在任何时候保存,而不仅仅是在创建时。当然,如果只需要完全重置,您的最好是在逻辑错误-编译器会抱怨的语法错误。谢谢,复制似乎是解决我的问题的最好办法。@MSalters使用
const
非常好的主意。请尝试!捕获的变量的初始值不需要存储,因为原始
i
是通过值捕获的,因此不需要“接触”是的,但原始的
i
可能早已超出范围。在您的问题中,您不太清楚为什么要刷新/重置lambda对象,因此我尝试以最小的假设逐字解决问题-仅给定lambda对象,尝试重置它或进行“刷新”复制。在您的代码中,将有两个版本的
i
:一个是局部变量(始终保持不变),其中一个是lambda中的值copy。但是每次调用lambda时,该副本都会被修改,因此您必须返回原始的
i
来获得起始值,您不能仅通过查看lambda对象本身来获得它。我明白您现在的意思。但在我看来,重建lambda对象d类似于实例化一个函子的类,从而“重新捕获”最初使用的
i
。这就是为什么我尝试
decltype(gen_lam)
作为(如愿以偿的)手段来获取对象的类型