1
votes

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;
}
1
Compiles with Boost 1.59 and g++ 5.3. Also with whatever clang version Apple LLVM 7.0.2 corresponds to. What are you building with?rhashimoto
@rhashimoto Glad to know it works on your platform. I'm building with Apple LLVM 7.1 and Boost1.58. I'll try new version of boost and see if it works.DXM
Not entirely on point, but I would probably use a lambda here instead of std::bind.rhashimoto

1 Answers

0
votes

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