Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a lambda in a function with a capture?

Tags:

c++

lambda

My title is my main question. The code below shows what i want to do, but it causes an error.

class B
{
public:
    void DoSomething(void (*func)())
    {
        func();
    }
};

class A
{
public:
    int x;
    void Start(B* b)
    {
        auto func = [this]()->void
        {
            this->x++;
        };
        b->DoSomething(func);
    }
};

If I remove the "this" keyword, then the program works, but then I cant reference the x variable.

So how can I achieve this?

like image 878
Assassinbeast Avatar asked Feb 18 '15 00:02

Assassinbeast


2 Answers

Change

void DoSomething( void (*func)() )

to

void DoSomething( std::function<void()> func )

Your current parameter type void (*func)() is a function pointer, which is a type of callable (something that can be called like a function) that doesn't hold state. That is why your variable this can't be passed into the function.

Only lambdas that capture nothing can be converted to a stateless function pointer.

std::function however can represent (almost) anything callable. It could be a raw function, or an instance of a class that implements operator(), or it could be your lambda holding state.

like image 165
Drew Dormann Avatar answered Sep 28 '22 05:09

Drew Dormann


An alternative is to simply use templates to avoid the potential overhead associated with large lambdas that need to be packaged by std::function.

#include <functional>

using namespace std;

template<typename Callable> 
void DoSomething(Callable c) { c(); }  // calls the lambda with no args

int main() 
{   
     DoSomething([]{ printf("Hello\n"); });   
     DoSomething([msg = "World"] { printf("%s\n", msg); });
}

Live Code: http://goo.gl/LMvm3a

like image 38
rparolin Avatar answered Sep 28 '22 04:09

rparolin