Boost logo

Boost :

Subject: Re: [boost] [smart_ptr] enable_shared_from_this and multiple inheritance solution
From: Ansel Sermersheim (agserm_at_[hidden])
Date: 2010-11-29 22:56:19


Philippe Cayouette <pcayouette_at_[hidden]> writes:

> On 10-11-28 03:02 PM, Ansel Sermersheim wrote:
>> In my solution, my enable_shared_from_polymorphic<T> class is just a
>> shim that inherits virtually from enable_shared_from_polymorphic_base,
>> which is not a template type. The base class holds a weak pointer,
>> which can be dynamic_pointer_cast by the child class when needed.
>
> Interesting idea, you resolve the problem of multiple inheritance with
> virtual inheritance. Having a single internal weak_ptr is surely a
> better idea than having a lot of them.

>> This allows your example to work as expected by merely inheriting from
>> enable_shared_from_polymorphic<T> rather than
>> enable_shared_from_this<T>.
>
> Did you tried your code on GCC? I just applied your patch and I think
> I am encountering the same problem as my example: on GCC, the function
> sp_enable_shared_from_this that is called is the one with the variable
> arguments (...), since the compiler cannot be sure of the value of T
> in the expression enable_shared_from_polymorphic< T > (it might be
> Base1 or Base2). On VS2005, the compiler chooses Base1 (in the
> original example) and thus, the pe->_internal_accept_owner function is
> called on the unique enable_shared_from_polymorphic_base and
> everything works (I guess, I didn't try).

This is rather puzzling. I do develop on GCC, I tested with:

bash$ g++ --version
g++ (Debian 4.4.5-6) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.

However, your idea of having the _internal_accept_owner function take
an enable_shared_from_polymorphic base makes perfect sense, and I have
made that change. Hopefully that builds more happily for you.

>> If anyone is interested in the code, it can be found at:
>>
>> http://208.106.110.44/~ansel/boost/enable_shared_from_polymorphic.patch
>>
>> This patch is against the current SVN version of boost.
>>
>> The pro of this method is that the class can be used identically to
>> the way that enable_shared_from_this is used. A downside is that any
>> class deriving from enable_shared_from_polymorphic<T> becomes
>> polymorphic and incurs all the cost thereof.
>
> IMHO, I think the biggest downside of your method is the usage of
> dynamic_pointer_cast, not the polymorphic costs. In fact, dynamic
> casts are non-deterministic and need RTTI, which is not always enabled
> depending on the environment (e.g. VxWorks 653 with cert). Real-time
> applications often disable RTTI to make sure they stay deterministic.

Very good point, and one I often miss since most projects I work on
use RTTI extensively.

>> This cost could potentially be mitigated if these classes used
>> static_pointer_cast instead of dynamic_pointer_cast. However, I am not
>> familiar enough with the appropriate areas of the C++ standard to be
>> sure that would work in cases of multiple inheritance, precisely when
>> these classes are useful.
>
> If you manage to make this work with static_pointer_cast instead of
> dynamic_pointer_cast, it would be the perfect solution to me... but I
> am not sure it is possible.

After mulling this over for some time, I _think_ I have come up with a
solution that mitigates all these problems.

I have a new patch up, at the same URL. In order to make this
mechanism work, I had to add a new constructor to
boost::shared_ptr<T>, which I am loath to do. Given that downside the
patch appears to work properly. It also adds a free function
boost::shared_from<T>(T*) which returns a boost::shared_ptr<T>.

The only cast that occurs in this code is a static_cast that downcasts
from enable_shared_from_polymorphic<T> to T. I have read the relevant
portions of the standard several times and I beleive this is valid,
but I would definitely be curious if wiser heads agree with my reading.

I would be very curious to hear if this new patch compiles
successfully on your system.

Thanks for your feedback,

Ansel


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk