Weaving lambda in C ++ 11 ... maybe?

I have a situation where I have a lambda as a member variable that is created by a specific function call. The problem is that he captures this as part of his work. Later, I want to be able to copy the entire object ...

However, during copying, I do not know how the lambda was created (it could be defined at several points through different code paths). Therefore, I do not understand a little what to add to the copy constructor. Ideally, I would like to "reconfirm" the lambda bindings to the newly created "this".

Is it possible?

Here is a sample code:

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

Thanks in advance.

+4
source share
2 answers

The problem you see is that the this pointer is written to lambda, but now you are executing a copy of the function from another object. It works in your example because both objects exist, but it is a lively pointer awaiting its existence.

The cleanest way to do this is to change your std::function and your lambdas to accept the argument of the pointer to the class and use this passed in the pointer, instead of capturing it. Depending on the contents of your lambda, you can choose values.

 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 example

+5
source

I do not think you can change the closure. If you need a function to work with another object, you need to pass a pointer to the object as an argument to the function:

 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; }; 
+3
source

All Articles