Ручка подключения / отключения многих сигналов / слотов с Boost :: сигналы2 - PullRequest
4 голосов
/ 07 июня 2011

Я начал использовать boost :: signal2 вместо моего старого сигнала-кода. У меня проблема с администрированием нескольких соединений. Вот моя проблема:

У меня много экземпляров класса Person:

class Person {
public:
    void SetName (string new_name)
    {
        name = new_name;
        NameChange (name);
    }

    string name;
    boost::signals2::signal<Person*> NameChange;
};

У меня также есть браузер людей, который должен отслеживать подмножество всех доступных людей на предмет изменений. Поскольку люди могут приходить и уходить из этого подмножества, у меня должен быть способ обработки объектов подключения, и я создал класс (ConnectionList) для обработки этого:

class ConnectionList
{
public:
    virtual ~ConnectionList () // drops all connections in "list"
    void add (boost::signals2::connection& conn); // adds "conn" to "list"
private:
    std::vector<boost::signals2::connection> list;
};

class PeopleBrowser
{
public:
    void AddPerson (Person& p)
    {
        name_change_connections.add (p.NameChange.connect (...));
    }
private:
    ConnectionList name_change_connections;
};

Это все хорошо, соединения сбрасываются при удалении PeopleBrowser, и есть хороший способ добавить новые соединения.

Однако нам нужно добавить другой метод RemovePerson, и этот метод должен удалить соединения с сигналом NameChange этого экземпляра Person.

Вот где я застрял. Я думаю, я мог бы сделать ConnectionList шаблоном и использовать список, который содержит структуру со ссылкой на сигнал, а также соединение, а затем добавить метод, который отбрасывает все соединения с этим сигналом.

Но похоже, что это такой распространенный случай (по крайней мере, в моем мире у меня есть около 20 классов в этом единственном приложении, которому нужна эта функциональность), поэтому я думаю, что должен быть лучший способ справиться с этим?

По крайней мере, есть ли способ получить ссылку на подключенный сигнал от объекта подключения?

Возможно, libsigc ++ справится с этим лучше / по-другому?

Ответы [ 2 ]

3 голосов
/ 07 июня 2011

Как насчет:

class PeopleBrowser
{
public:
    void AddPerson (Person& p)
    {
        name_change_connections[&p] = p.NameChange.connect(...);
    }
    void RemovePerson(Person& p)
    {
         name_change_connections.erase(&p);
    }

private:
    std::map<Person*, boost::signals2::scoped_connection> name_change_connections;
};

Возможно, вы также захотите взглянуть на автоматическое управление соединениями .

0 голосов
/ 07 июня 2011

Я сам не пробовал, но согласно документация для буста

Когда могут произойти разъединения? (Средний)

Отключение сигнала / слота происходит при возникновении любого из следующих условий:

  • Соединение явно отключается с помощью метода disconnect соединения напрямую или косвенно с помощью метода disconnect сигнала или деструктора scoped_connection.
  • Объект, отслеживаемый слотом, уничтожен.
  • Сигнал уничтожен.

Если вы не используете scoped_connection, соединение между сигналом и слотом будет действовать до тех пор, пока один из них не будет уничтожен. Так что, насколько я понимаю, вам не нужно хранить объекты соединения в векторе. Просто подключите ваш сигнал к вашему слоту, как вы делаете сейчас.

Когда ваш наблюдаемый объект выходит из области видимости, он сам удаляет соединение.

Это гораздо более простой дизайн.

...