问题
I want to use boost signals2 with automatic connection management in a multithreaded application. My class inherits from enable_shared_from_this<>
and i want to connect a member method from within another member method. The connection might be rebuilt frequently so my code should be as fast as possible (despite from the boost signals2 performance itself):
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 ();
};
I know that my design goals might be conflicting (automatic connection management and thread safety but also fast code) but anyway:
Why does
enable_shared_from_this<>
lack direct access to the embeddedweak_ptr<>
? I can't see an opposing reason. Is there no use case similar to mine?Is there a faster workaround than the one above?
Edit:
I know i can do somethink like this, but i want to avoid the additional storage/init-check penalty:
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;
};
回答1:
The reason you don't have access to the weak_ptr
is that enable_shared_from_this
doesn't have to use one. Having a weak_ptr
is simply one possible implementation of enable_shared_from_this
. It is not the only one.
Since enable_shared_from_this
is part of the same standard library as shared_ptr
, a more efficient implementation could be used than directly storing a weak_ptr
. And the committee doesn't want to prevent that optimization.
// ok, but slow?! two temporary smart pointers
That's only one temporary smart pointer. Copy elision/movement should take care of anything but the first object.
回答2:
It might be because there are no shared_ptr
referencing the Cat
instance. weak_ptr
requires there to be at least one active shared_ptr
.
Try placing a shared_ptr
as member variable and assign to it first in the connect
method:
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 ()));
}
};
But basically, there can be no weak_ptr
if there are no shared_ptr
.
And if all shared_ptr
disapear while the weak_ptr
is still in use, then the weak_ptr
could point to an non-existant object.
Note: My test should not be used in production code as it will cause the object to never be deallocated.
来源:https://stackoverflow.com/questions/15928924/why-does-enable-shared-from-this-lack-direct-access-to-the-embedded-weak-ptr