Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing std::function from within itself (by move-assignment to *this?)

Is it possible to replace one std::function from within itself with another std::function?

The following code does not compile:

#include <iostream>
#include <functional>

int main()
{
    std::function<void()> func = []()
    {
        std::cout << "a\n";
        *this = std::move([]() { std::cout << "b\n"; });
    };
    func();
    func();
    func();
}

Can it be modified to compile?
The error message right now is: 'this' was not captured for this lambda function - which I completely understand. I don't know, however, how I could capture func's this-pointer. I guess, it is not even a std::function inside the lambda, yet?! How can this be done?

Background: What I want to achieve is the following: In the first invocation of a given std::function, i would like do some initialization work and then replace the original function with an optimized one. I want to achieve this transparently for the user of my function.

The expected output of the example above is:

a
b
b

like image 855
j00hi Avatar asked Jan 29 '23 01:01

j00hi


1 Answers

You cannot use this inside a lambda to refer to the lambda. this will only refer to the enclosing class, which in your case there is none so you cannot use this. What you can do however is capture func and reassign that:

std::function<void()> func = [&func]()
{
    std::cout << "a\n";
    func = []() { std::cout << "b\n"; }; // note the missing move, a lambda
                                         // is already an rvalue
};

Note however that if you let func outlive its scope (say by returning it from a function by value) without calling it first (effectively reassigning the stored function object) then you'll get a dangling reference.

I guess, it is not even a std::function inside the lambda, yet?!

It actually is. A name comes into scope right after its declarator, so right before the =, func of type std::function<void()> is introduced. So at the point where you introduce the lambda, you can already capture func.

like image 186
Rakete1111 Avatar answered Feb 06 '23 16:02

Rakete1111