Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with binding non static function to callback [duplicate]

Tags:

c++

I can't bind a non-static member function to a callback. I have to bind the test2 class member function here() to test1 member callBack which is a std::function, but I could not find way to do this. Anyone can suggest me if you have any idea.

Show in code

#include <iostream>
#include <stdint.h>
#include <functional>
using namespace std;

class test1{
public:
    typedef std::function<void()> callback_function_t;
    callback_function_t callBack;
    void setCallback(callback_function_t _callBackfn){
        callBack = std::move(_callBackfn);
    }

    void check(void){
        callBack();
    }
};

class test2{
public:
    void here(){
        cout << "safsafsdf" << endl;
    }
};

int main(){
    test1 t1;
    test2 t2;
    t1.setCallback(t2.here); // Can't Works
    return 0;
}

must be set in test1 callback.

like image 446
Ajay Ambaliya Avatar asked Mar 03 '23 13:03

Ajay Ambaliya


2 Answers

The issue is that when creating the std::function you have also to provide the instance of the class the member function has to be invoked on. The other answer uses std::bind, which is a possible solution. I would suggest using a lambda function as an alternative, for readability:

t1.setCallback([&t2](){t2.here();}); 

Note that here you are capturing t2 as a reference, so you must ensure that t2 is alive when t1 uses the callback.

Alternatively you can capture by value (making a copy)

t1.setCallback([t2]() mutable {t2.here();}); 

and you need the mutable keyword to allow the call of a non-const qualified member function

Finally you can also move t2 inside the lambda, avoiding a copy

t1.setCallback([t2 = std::move(t2)]() mutable {t2.here();}); 

this is the generalized capture, available from C++14. In your specific example using the std::move will hardly make any difference, but in general, if the object is complex, this might be of use.

like image 132
CuriouslyRecurringThoughts Avatar answered Mar 24 '23 17:03

CuriouslyRecurringThoughts


The syntax you're using for binding the this pointer to t1 isn't correct. You can't simply write t2.here in order to get a function which, when called, is essentially the same as t2.here().

One possible solution is to bind the this object via std::bind(), e.g.

t1.setCallback(std::bind(&test2::here, t2));

But keep in mind, this creates a copy of t2 inside the function object finally stored inside t2.callBack. Modifications to t2 don't affect t1.callBack. If you're sure t1 always outlives t2, you can also create a reference

    t1.setCallback(std::bind(&test2::here, std::ref(t2)));
like image 37
phlipsy Avatar answered Mar 24 '23 16:03

phlipsy