Я хочу использовать boost сигналы2 с автоматическим управлением подключением в многопоточном приложении. Мой класс наследует от enable_shared_from_this<>
и я хочу подключить метод-член из другого метода-члена. Соединение может часто перестраиваться, поэтому мой код должен быть настолько быстрым, насколько это возможно (несмотря на саму производительность сигналов сигнала2):
typedef boost::signals2::signal<void ()> signal_type;
struct Cat : public enable_shared_from_this<Cat>
{
void meow ();
void connect (signal_type& s)
{
// can't write this
s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (weak_from_this ()));
// ok, but slow?! two temporary smart pointers
weak_ptr<Cat> const myself (shared_from_this ());
s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (myself));
}
// i am missing something like this in the base class
// protected:
// weak_ptr<Cat> const& weak_from_this ();
};
Я знаю, что мои цели разработки могут быть противоречивыми (автоматическое управление соединениями и безопасность потоков, но также быстрый код), но в любом случае:
Почему enable_shared_from_this<>
отсутствие прямого доступа к встроенным weak_ptr<>
? Я не вижу противоположной причины. Нет ли варианта использования, аналогичного моему?
Есть ли более быстрое решение, чем приведенное выше?
Редактировать:
Я знаю, что могу сделать что-то подобное, но я хочу избежать дополнительного наказания за хранение / инициализацию:
template <typename T>
struct enable_weak_from_this : public enable_shared_from_this<T>
{
protected:
weak_ptr<T> /* const& */ weak_from_this ()
{
if (mWeakFromThis.expired ())
{
mWeakFromThis = this->shared_from_this ();
}
return mWeakFromThis;
}
private:
weak_ptr<T> mWeakFromThis;
};
Причина, по которой у вас нет доступа к weak_ptr
в том, что enable_shared_from_this
не должен использовать один. Иметь weak_ptr
это просто один возможный реализация enable_shared_from_this
, Это не единственный.
поскольку enable_shared_from_this
является частью той же стандартной библиотеки, что и shared_ptr
можно использовать более эффективную реализацию, чем непосредственное хранение weak_ptr
, И комитет не хочет предотвращать эту оптимизацию.
// хорошо, но медленно ?! два временных умных указателя
Это только один временный умный указатель. Копия elision / motion должна заботиться обо всем, кроме первого объекта.
Это может быть потому, что нет shared_ptr
ссылаясь на Cat
пример. weak_ptr
требует, чтобы был хотя бы один активный shared_ptr
,
Попробуйте разместить shared_ptr
в качестве переменной-члена и назначить ей сначала в connect
метод:
typedef boost::signals2::signal<void ()> signal_type;
struct Cat : public enable_shared_from_this<Cat>
{
void meow ();
boost::shared_ptr<Cat> test;
void connect (signal_type& s)
{
test = shared_from_this();
s.connect (signal_type::slot_type (&Cat::meow, this, _1).track (weak_from_this ()));
}
};
Но в принципе не может быть никакого weak_ptr
если нет shared_ptr
,
И если все shared_ptr
исчезнуть в то время как weak_ptr
все еще используется, то weak_ptr
может указывать на несуществующий объект.
Примечание. Мой тест не следует использовать в производственном коде, поскольку он никогда не будет освобожден.