I have simple base and derived class that I want both have shared_from_this()
.
This simple solution:
class foo : public enable_shared_from_this<foo> { void foo_do_it() { cout<<"foo::do_it\n"; } public: virtual function<void()> get_callback() { return boost::bind(&foo::foo_do_it,shared_from_this()); } virtual ~foo() {}; }; class bar1 : public foo , public enable_shared_from_this<bar1> { using enable_shared_from_this<bar1>::shared_from_this; void bar1_do_it() { cout<<"foo::do_it\n"; } public: virtual function<void()> get_callback() { return boost::bind(&bar1::bar1_do_it,shared_from_this()); } };
Causes exception tr1::bad_weak_ptr
in following code:
shared_ptr<foo> ptr(shared_ptr<foo>(new bar1)); function<void()> f=ptr->get_callback(); f();
So after "googling" I have found following solution:
class bar2 : public foo { void bar2_do_it() { cout<<"foo::do_it\n"; } shared_ptr<bar2> shared_from_this() { return boost::static_pointer_cast<bar2>(foo::shared_from_this()); } public: virtual function<void()> get_callback() { return boost::bind(&bar2::bar2_do_it,shared_from_this()); } };
And now it works.
Is there any better and more convinient and correct way to enable_shared_from_this
for both parent and child?
Thanks
std::enable_shared_from_this is a standard solution that enables a shared_ptr managed object to acquire a shared_ptr to itself on demand. A class T that publicly inherits an std::enable_shared_from_this<T> encapsulates a std::weak_ptr<T> to itself that can be converted to a std::shared_ptr<T> when needed.
shared_from_this. returns a shared_ptr which shares ownership of *this. (public member function)
The OP solution can be made more convenient by defining the following on the base class.
protected: template <typename Derived> std::shared_ptr<Derived> shared_from_base() { return std::static_pointer_cast<Derived>(shared_from_this()); }
This can be made more convenient by placing it in a base class (for reuse).
#include <memory> template <class Base> class enable_shared_from_base : public std::enable_shared_from_this<Base> { protected: template <class Derived> std::shared_ptr<Derived> shared_from_base() { return std::static_pointer_cast<Derived>(shared_from_this()); } };
and then deriving from it as follows.
class foo : public enable_shared_from_base<foo> { void foo_do_it() { std::cout << "foo::do_it\n"; } public: virtual std::function<void()> get_callback() { return boost::bind(&foo::foo_do_it, shared_from_base<foo>()); } }; class bar1 : public foo { void bar1_do_it() { std::cout << "bar1::do_it\n"; } public: virtual std::function<void()> get_callback() override { return boost::bind(&bar1::bar1_do_it, shared_from_base<bar1>()); } };
Sorry, but there isn't.
The problem is that shared_ptr<foo>
and shared_ptr<bar1>
are different types. I don't understand everything that's going on under the hood, but I think that when the constructor returns and is assigned to a shared_ptr<foo>
, the internal weak_ptr<bar1>
sees that nothing is pointing to it (because only a shared_ptr<bar1>
would increment the counter) and resets itself. When you call bar1::shared_from_this
in get_callback
, you get the exception because the internal weak_ptr
isn't pointing to anything.
Essentially, enable_shared_from_this
only seems to work transparently from a single class in a hierarchy. If you try implementing it manually, the problem should become obvious.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With