Search code examples
c++c++11booststd-functionstdbind

Pass std::bind object with bind member function to a function


I want to connect a callback function to a boost signal through a public function. I can pass a function pointer just fine, but if I try to use std::bind to pass a member function, it will not compile. Giving me error saying no viable conversion. What type should I use for the App::SetCallback function argument?

#include <functional>
#include <boost/signal.hpp>
using namespace std::placeholders;  // for _1, _2, _3...

//plain simple call back function
void SimpleCallback(int value) {
//do nothing
}
//class contains a boost::signal, set callback through a public function
class App {
public:
    App() : sig_()
    {}
    typedef boost::signal<void (int value)> SigType;
    typedef std::function<void (int value)> CallbackFunType;
    //connect signal to a callback function
    void SetCallback(CallbackFunType callback) {
        sig_.connect(callback);
    }
//private: //comment this out for testing purpose.
    SigType sig_; //this is the boost::signal
};

//class that has member callback function
class MyCallback {
public:
    MyCallback():
    val(0), app()
    {}
    void MemberCb(int value){
      val = value;
    }
    void Connect() {
        auto bind_fun = std::bind(&MyCallback::MemberCb, this, _1);
        app.SetCallback(bind_fun); //this will not compile, no viable conversion
        app.sig_.connect(bind_fun); //this is fine
        app.SetCallback(SimpleCallback); //this is fine
    }
private:
    int val;
    App app;
};

int main(int argc, char **argv) {
    MyCallback my_cb;
    my_cb.Connect();
    return 1;
}

----------------UPDATE-----------------

Reading boost signal documentation more carefully, I learned that I can pass slot type. This solves my problem

#include <functional>
#include <boost/signal.hpp>
using namespace std::placeholders;  // for _1, _2, _3...

//plain simple call back function
void SimpleCallback(int value) {
//do nothing
}
//class contains a boost::signal, set callback through a public function
class App {
public:
    App() : sig_()
    {}
    typedef boost::signal<void (int value)> SigType;
    typedef SigType::slot_type CallbackFunType;
    //typedef std::function<void (int value)> CallbackFunType;
    //connect signal to a callback function
    void SetCallback(CallbackFunType callback) {
        sig_.connect(callback);
    }
//private: //comment this out for testing purpose.
    SigType sig_; //this is the boost::signal
};

//class that has member callback function
class MyCallback {
public:
    MyCallback():
    val(0), app()
    {}
    void MemberCb(int value){
      val = value;
    }
    void Connect() {
        auto bind_fun = std::bind(&MyCallback::MemberCb, this, _1);
        app.SetCallback(bind_fun); //using SigType::slot_type
        app.sig_.connect(bind_fun);
        app.SetCallback(SimpleCallback);
    }
private:
    int val;
    App app;
};

int main(int argc, char **argv) {
    MyCallback my_cb;
    my_cb.Connect();
    return 1;
}

Solution

  • Reading boost signal documentation more carefully, I learned that I can pass slot type. This solves my problem

    #include <functional>
    #include <boost/signal.hpp>
    using namespace std::placeholders;  // for _1, _2, _3...
    
    //plain simple call back function
    void SimpleCallback(int value) {
    //do nothing
    }
    //class contains a boost::signal, set callback through a public function
    class App {
    public:
        App() : sig_()
        {}
        typedef boost::signal<void (int value)> SigType;
        typedef SigType::slot_type CallbackFunType;
        //typedef std::function<void (int value)> CallbackFunType;
        //connect signal to a callback function
        void SetCallback(CallbackFunType callback) {
            sig_.connect(callback);
        }
    //private: //comment this out for testing purpose.
        SigType sig_; //this is the boost::signal
    };
    
    //class that has member callback function
    class MyCallback {
    public:
        MyCallback():
        val(0), app()
        {}
        void MemberCb(int value){
          val = value;
        }
        void Connect() {
            auto bind_fun = std::bind(&MyCallback::MemberCb, this, _1);
            app.SetCallback(bind_fun); //using SigType::slot_type
            app.sig_.connect(bind_fun);
            app.SetCallback(SimpleCallback);
        }
    private:
        int val;
        App app;
    };
    
    int main(int argc, char **argv) {
        MyCallback my_cb;
        my_cb.Connect();
        return 1;
    }