Сохранение сигнала boost::signals2 на карте?

Я столкнулся со следующей проблемой: я хочу сохранить несколько boost::signals2 сигнальных переменных на карте. Поскольку эти сигналы не копируются, очевидно, что это не сработает. Как я могу обойти это? Я уже нашел этот старый вопрос. В нем постер предлагает хранить сигналы как shared_ptr. Это единственный способ сделать это? Есть ли у него недостатки или, что более важно, безопасно?


person Gnosophilon    schedule 04.06.2012    source источник
comment
Вы также можете сохранить boost::signals2::signal *, но shared_ptr — это просто удобный способ сделать это, не беспокоясь об удалении объекта. Что вы подразумеваете под безопасным?   -  person wroniasty    schedule 04.06.2012
comment
@wroniasty Мне просто интересно, предназначен ли boost::signals2 для использования таким образом. Я не хочу вводить код, основанный на недокументированном поведении.   -  person Gnosophilon    schedule 04.06.2012
comment
Что ж, класс, который не может безопасно храниться в shared_ptr, не работает.   -  person jalf    schedule 04.06.2012


Ответы (3)


Как было указано некоторыми комментаторами: использование shared_ptrs для сигналов совершенно безопасно. Моя реализация работает и была тщательно протестирована, и я рад сообщить, что проблем действительно нет :)

person Gnosophilon    schedule 04.09.2012

Если сигналы не предназначены для совместного использования, вы можете хранить boost::signal объектов, выделенных в куче, внутри Контейнер Boost Pointer:

Контейнер Boost.Pointer предоставляет контейнеры для хранения объектов, выделенных в куче, безопасным для исключений способом и с минимальными издержками.

Контейнер указателя повышения хранит указатели на свои элементы и автоматически удаляет эти объекты кучи, когда это необходимо. API пытается скрыть тот факт, что элементы хранятся по указателю, и по возможности возвращает ссылки на элементы.

Пример:

#include <iostream>
#include <map>
#include <string>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/signals.hpp>

void foo() {std::cout << "foo\n";}

void bar() {std::cout << "bar\n";}

int main()
{
    typedef boost::signal<void ()> Signal;
    boost::ptr_map< std::string, Signal> sigmap;
    sigmap["foo"].connect(&foo);
    sigmap["bar"].connect(&bar);
    sigmap["foo"](); // emit signal associated with "foo"
    sigmap["bar"](); // emit signal associated with "bar"
}
person Emile Cormier    schedule 06.03.2013

Поскольку он не копируется и не перемещается (возможно, он изменился в последней версии). Для std::map, если вы не хотите использовать shared_ptr, вы можете использовать оператор [] вместо методов вставки или замены, поскольку оператор [] создает mapped_type, если ключевое_значение не существует. Очевидно, что это не решает проблему, когда вы хотите добавить сигнал с ранее назначенными слотами.

typedef boost::signal2... Signal;
std::map<int, Signal> sigmap;
sigmap[1]; // constructs signal using default constructor
sigmap[2].connect(slot); // constructs signal and connects slot
person Boris Lyubimov    schedule 09.12.2014