Как передать обратные вызовы сигнала (используя boost::bind)

Я пишу обертку для boost::signals2::signal, чтобы получить более чистый и простой в использовании интерфейс. Вот что я придумал:

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

Я не уверен, что это лучший интерфейс-оболочка, который я могу придумать, и создание открытого члена SomethingHappened может иметь некоторые недостатки. Хотя я не против услышать ваше мнение об этом, это не то, о чем этот вопрос.

Мне интересно, как передать обратный вызов оператору +=. Как я писал в ClassThatListensForEvents, обратный вызов функции не представляет проблемы, но использование результата bind дает массу трудночитаемых ошибок компилятора шаблонов.


person Jonatan    schedule 26.02.2013    source источник
comment
Прежде чем приступить к написанию такой оболочки, стоит прочитать Дизайн Rational".   -  person Igor R.    schedule 26.02.2013
comment
Я читал это однажды и согласен с этим в общем контексте Boost, но в контексте моего приложения я должен решать, и мне вроде как нравится этот чистый интерфейс, и недостатки меня не сильно беспокоят. . Но += — это просто сахар, настоящая причина написания обертки — скрыть класс boost::signals2::signal от пользователей класса, чтобы уменьшить сложность и разрешить другие реализации в будущем.   -  person Jonatan    schedule 26.02.2013


Ответы (2)


Ваш сигнал имеет сигнатуру void(), поэтому он не принимает никаких параметров. Вы пытаетесь назначить объект boost::bind, который принимает один параметр (поскольку он использует _1), что несовместимо. Поэтому вы получаете ошибку. Непонятно, откуда именно вы ожидаете получить параметр ev для event_handler. Если вы привяжете фактическое значение вместо _1, подписи будут совместимы.

person interjay    schedule 26.02.2013

Подпись сигнала и обратного вызова отличается, я думаю, что это ошибка

person kassak    schedule 26.02.2013
comment
Спасибо, но это была просто опечатка, которой нет в реальном коде. Я обновил вопрос. - person Jonatan; 26.02.2013