[shared_ptr] Multiple enable_shared_from_this in inheritance tree

There was a Code Project article (http://www.codeproject.com/Articles/286304/Solution-for-multiple-enable_shar...) about a problem using multiple enable_shared_from_this derivations in an inheritance tree. Does this problem actually exist in the current Boost implementation ? If so, should there not be some documentation regarding it ?

----- Mail original -----
De: "Edward Diener" <eldiener@tropicsoft.com> À: boost-users@lists.boost.org Envoyé: Dimanche 25 Mars 2012 21:37:55 Objet: [Boost-users] [shared_ptr] Multiple enable_shared_from_this in inheritance tree
There was a Code Project article (http://www.codeproject.com/Articles/286304/Solution-for-multiple-enable_shar...) about a problem using multiple enable_shared_from_this derivations in an inheritance tree.
Does this problem actually exist in the current Boost implementation ?
I've been trapped by this two years ago, and now under 1.48 code below throws under VS2010 when calling B::shared_from_this(). // BEGIN #include <boost/smart_ptr/enable_shared_from_this.hpp> #include <boost/make_shared.hpp> struct A : boost::enable_shared_from_this <A> {}; struct B : boost::enable_shared_from_this <B> {}; struct C : A, B {}; int main() { boost::make_shared <C>()->A::shared_from_this(); boost::make_shared <C>()->B::shared_from_this(); return 0; } // END weak_this_ is null so you have a bad_weak_ptr exception in shared_count::shared_count( weak_count const & r ). Root problem seems to be that template function sp_enable_shared_from_this is only called for first matching specialization. Following code does not throw : (*DISCLAIMER* this could make your computer explode, and is probably utterly wrong anyway) boost::shared_ptr <C> c = boost::make_shared <C>(); c->A::shared_from_this(); boost::detail::sp_enable_shared_from_this (&c, c.get(), static_cast <boost::enable_shared_from_this<B>* > (c.get())); c->B::shared_from_this(); Regards, Ivan

On 3/26/2012 4:39 AM, ivan.lelann@free.fr wrote:
----- Mail original -----
De: "Edward Diener"<eldiener@tropicsoft.com> À: boost-users@lists.boost.org Envoyé: Dimanche 25 Mars 2012 21:37:55 Objet: [Boost-users] [shared_ptr] Multiple enable_shared_from_this in inheritance tree
There was a Code Project article (http://www.codeproject.com/Articles/286304/Solution-for-multiple-enable_shar...) about a problem using multiple enable_shared_from_this derivations in an inheritance tree.
Does this problem actually exist in the current Boost implementation ?
I've been trapped by this two years ago, and now under 1.48 code below throws under VS2010 when calling B::shared_from_this().
// BEGIN #include<boost/smart_ptr/enable_shared_from_this.hpp> #include<boost/make_shared.hpp>
struct A : boost::enable_shared_from_this<A> {};
struct B : boost::enable_shared_from_this<B> {};
struct C : A, B {};
int main() { boost::make_shared<C>()->A::shared_from_this(); boost::make_shared<C>()->B::shared_from_this();
return 0; } // END
weak_this_ is null so you have a bad_weak_ptr exception in shared_count::shared_count( weak_count const& r ). Root problem seems to be that template function sp_enable_shared_from_this is only called for first matching specialization.
Following code does not throw : (*DISCLAIMER* this could make your computer explode, and is probably utterly wrong anyway)
boost::shared_ptr<C> c = boost::make_shared<C>(); c->A::shared_from_this(); boost::detail::sp_enable_shared_from_this (&c, c.get(), static_cast<boost::enable_shared_from_this<B>*> (c.get())); c->B::shared_from_this();
Thanks ! I am not actually deriving from 2 classes, each one of which is derived from enable_shared_from_this<> as in your example. My case was initially that I had a base class deriving from enable_shared_from_this<> and another class deriving from that base class and its own enable_shared_from_this<>. I changed so that the base class's derivation serves for the derived class and wrote a shared_from_this() member function for the derived class which casts the result of the base class's shared_from_this() to a shared_ptr<Derived>. That appears to work fine. My main point is that if having more than one enable_shared_from_this<> in the inheritance hierarchy normally fails, this should be documented with the proper information on how to workaround the problem.

----- Mail original -----
De: "Edward Diener" <eldiener@tropicsoft.com> À: boost-users@lists.boost.org Envoyé: Lundi 26 Mars 2012 23:54:21 Objet: Re: [Boost-users] [shared_ptr] Multiple enable_shared_from_this in inheritance tree
On 3/26/2012 4:39 AM, ivan.lelann@free.fr wrote:
----- Mail original -----
De: "Edward Diener"<eldiener@tropicsoft.com> À: boost-users@lists.boost.org Envoyé: Dimanche 25 Mars 2012 21:37:55 Objet: [Boost-users] [shared_ptr] Multiple enable_shared_from_this in inheritance tree
There was a Code Project article (http://www.codeproject.com/Articles/286304/Solution-for-multiple-enable_shar...) about a problem using multiple enable_shared_from_this derivations in an inheritance tree.
Does this problem actually exist in the current Boost implementation ?
I've been trapped by this two years ago, and now under 1.48 code below throws under VS2010 when calling B::shared_from_this().
// BEGIN #include<boost/smart_ptr/enable_shared_from_this.hpp> #include<boost/make_shared.hpp>
struct A : boost::enable_shared_from_this<A> {};
struct B : boost::enable_shared_from_this<B> {};
struct C : A, B {};
int main() { boost::make_shared<C>()->A::shared_from_this(); boost::make_shared<C>()->B::shared_from_this();
return 0; } // END
weak_this_ is null so you have a bad_weak_ptr exception in shared_count::shared_count( weak_count const& r ). Root problem seems to be that template function sp_enable_shared_from_this is only called for first matching specialization.
Following code does not throw : (*DISCLAIMER* this could make your computer explode, and is probably utterly wrong anyway)
boost::shared_ptr<C> c = boost::make_shared<C>(); c->A::shared_from_this(); boost::detail::sp_enable_shared_from_this (&c, c.get(), static_cast<boost::enable_shared_from_this<B>*> (c.get())); c->B::shared_from_this();
My case was initially that I had a base class deriving from enable_shared_from_this<> and another class deriving from that base class and its own enable_shared_from_this<>.
Precisely the issue I got when I discovered the problem.
My main point is that if having more than one enable_shared_from_this<> in the inheritance hierarchy normally fails, this should be documented with the proper information on how to workaround the problem.
I agree. I wondered how current C++11 standard libraries handled this. With VS2010, replacing "boost" with "std" made both "shared_from_this()" calls throw. (with two esft bases the compiler chooses a dummy specialization) Regards, Ivan

On 3/27/2012 5:08 AM, ivan.lelann@free.fr wrote:
snip...
My main point is that if having more than one enable_shared_from_this<> in the inheritance hierarchy normally fails, this should be documented with the proper information on how to workaround the problem.
I agree.
I wondered how current C++11 standard libraries handled this. With VS2010, replacing "boost" with "std" made both "shared_from_this()" calls throw. (with two esft bases the compiler chooses a dummy specialization)
I think it is quite simply that there can not be more than one enable_shared_from_this derivation in a hierarchy. Unfortunately one is left to discover this for himself. Similarly there is no mention in the docs that using shared_from_this() during construction is not going to work either. The documentation for enable_shared_from_this needs to be better.

----- Mail original -----
De: "Edward Diener" <eldiener@tropicsoft.com> À: boost-users@lists.boost.org Envoyé: Mercredi 28 Mars 2012 01:56:24 Objet: Re: [Boost-users] [shared_ptr] Multiple enable_shared_from_this in inheritance tree
On 3/27/2012 5:08 AM, ivan.lelann@free.fr wrote:
snip...
My main point is that if having more than one enable_shared_from_this<> in the inheritance hierarchy normally fails, this should be documented with the proper information on how to workaround the problem.
I agree.
I wondered how current C++11 standard libraries handled this. With VS2010, replacing "boost" with "std" made both "shared_from_this()" calls throw. (with two esft bases the compiler chooses a dummy specialization)
I think it is quite simply that there can not be more than one enable_shared_from_this derivation in a hierarchy. Unfortunately one is left to discover this for himself.
IIRC, with g++ (4.6) using its C++11's std instead of boost, I got a compile-time error. Something like "... is ambiguous". I'll try to check that as it is quite self-documenting. I failed to see how one can properly implement enable_shared_from_this without extra compiler support. BTW, you can throw even without multiple esft. With boost or VS2010's std: struct A { virtual void foo() {};}; struct B : A, boost::enable_shared_from_this <B> {}; int main() { A * pa = new B; boost::shared_ptr <A> spa (pa); // dummy sp_enable_shared_from_this called here as A do not inherit esft // shared_ptr <A> spa (new B) would have been ok boost::dynamic_pointer_cast <B> (spa)->shared_from_this(); // shared_from_this() throws bad_weak_ptr return 0; } Regards, Ivan
participants (2)
-
Edward Diener
-
ivan.lelann@free.fr