在c++11中重新绑定lambda.有可能吗

Rebinding lambda in c++11... is it possible?

本文关键字:绑定 lambda 有可能 c++11 新绑定      更新时间:2023-10-16

我有一种情况,我有一个lambda作为由某个函数调用创建的成员变量。问题是,它将此作为其操作的一部分。稍后,我希望能够复制整个对象。。。

然而,在复制时,我不知道lambda是如何创建的(它可能是通过不同的代码路径在几个位置定义的)。因此,对于在复制构造函数中放入什么,我有些不知所措。理想情况下,我希望将lambda的捕获"重新绑定"到创建的新"this"。

这有可能吗?

以下是一些示例代码:

#include <iostream>
#include <string>
#include <functional>
class Foo
{
  public:
    Foo () = default;
    ~Foo () = default;
    void set (const std::string & v)
    {
        value = v;
    }
    void set ()
    {
        lambda = [&]()
        {
            return this->value;
        };
    }
    std::string get ()
    {
        return lambda();
    }

    std::string value;
    std::function <std::string (void)> lambda;
};
int main ()
{
    Foo foo;
    foo.set ();
    foo.set ("first");
    std::cerr << foo.get () << std::endl; // prints "first"
    foo.set ("captures change");
    std::cerr << foo.get () << std::endl; // prints "captures change"
    Foo foo2 (foo);
    foo2.set ("second");
    std::cerr << foo.get () << std::endl; // prints "captures change" (as desired)
    std::cerr << foo2.get () << std::endl; // prints "captures change" (I would want "second" here)
    return 0;
}

提前谢谢。

您看到的问题是this指针被捕获到lambda中,但您现在正在从另一个对象执行函数的副本。它在您的示例中起作用,因为这两个对象都存在,但它只是一个等待发生的悬挂指针。

要做到这一点,最干净的方法是修改std::function和Lambda,使其采用指向类的指针的参数,并使用传入的指针而不是捕获它。根据lambda的内容,可以选择捕获值。

class Foo
{
  public:
    Foo () = default;
    ~Foo () = default;
    void set (const std::string & v)
    {
        value = v;
    }
    void set ()
    {
        lambda = [](Foo* self)
        {
            return self->value;
        };
    }
    std::string get ()
    {
        return lambda(this);
    }

    std::string value;
    std::function <std::string (Foo*)> lambda;
};

IDEOne 的示例

我认为您不能修改闭包。如果您需要函数对另一个对象进行操作,则需要将指向该对象的指针作为函数的参数:

class Foo
{
  public:
    Foo () = default;
    ~Foo () = default;
    void set (const std::string & v)
    {
        value = v;
    }
    void set ()
    {
        lambda = [](Foo* t)
        {
            return t->value;
        };
    }
    std::string get ()
    {
        return lambda(this);
    }
    std::string value;
    std::function <std::string (Foo*)> lambda;
};