c++boostboost-bindboost-signalsboost-signals2

How to pass signal callbacks (using boost::bind)


I'm writing a wrapper for boost::signals2::signal to get a cleaner, more easy to use interface. Here's what I've come up with:

#include <boost/signals2.hpp>

// Wrapper class template for boost::signals2::signal
template<typename T>
class Signal {
    typedef typename boost::signals2::signal<T> SignalType;
public:
    // Trigger the signal
    void operator() () { sig(); }

    // Attach a listener
    boost::signals2::connection operator+=(const typename SignalType::slot_type& slot)
        { return sig.connect(slot); }

private:
    SignalType sig;
};

class ClassThatGeneratesEvents {
public:
    void generateEvents(int n) {
        while (n-- > 0) {
            SomethingHappened();
        }
    }

    Signal<void ()> SomethingHappened;
};

void func()
{
    ;
}

class ClassThatListensForEvents {
public:
    ClassThatListensForEvents(ClassThatGeneratesEvents& ev) {
        received_count = 0;

        // This works
        ev.SomethingHappened += func;

        // This doesn't!
        ev.SomethingHappened += bind(&ClassThatListensForEvents::event_handler, this, _1);
    }

    void event_handler() {
        received_count++;
    }

    int received_count;
};

I'm not sure this is the best wrapper interface I can come up with, and making SomethingHappened a public member might perhaps have some drawbacks. While I don't mind hearing your opinions about that, it is not what this is question is about.

What I'm wondering is how to pass the callback to the += operator. As I've written in ClassThatListensForEvents a callback to a function is no problem, but using the result bind gives a ton of hard-to-read template compiler errors.


Solution

  • Your signal has a void() signature, so it takes no parameters. You are trying to assign a boost::bind object that takes one parameter (since it uses _1), which is incompatible. Therefore you get an error. It isn't clear where exactly you're expecting the ev parameter to event_handler to come from. If you bind an actual value instead of _1 the signatures will be compatible.