Boost logo

Boost :

Subject: Re: [boost] [smart_ptr] Moving cast for unique_ptr
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2015-10-07 20:57:52


On 8/10/2015 09:27, Karolin Varner wrote:
> On 10/07/2015 09:45 PM, Peter Dimov wrote:
>> template<class T, class U>
>> unique_ptr<T> dynamic_pointer_cast( unique_ptr<U> && r ) noexcept
>> {
>> T * p = dynamic_cast<T*>( r.get() );
>> if( p ) r.release();
>> return unique_ptr<T>( p );
>> }
[...]
> On 10/07/2015 09:03 AM, Gavin Lambert wrote:
>> On 7/10/2015 19:16, Vicente J. Botet Escriba wrote:
>>> Just wondering if we can not make dynamic_pointer_cast to work as your
>>> dynamic_moving_pointer_cast, when the parameter is a rvalue reference
>>
>> It would theoretically be possible if you have access to the
>> internals of shared_ptr (otherwise it would be no better than copying).
>
> We do have access to the internals of the boost smart pointers, so
> wecould provide a set of specialized moving casts for std::unique_ptr,
> boost::shared_ptr and boost::scoped_ptr.

unique_ptr is straightforward, as Peter Dimov has demonstrated above.
scoped_ptr is similarly straightforward. As I mentioned on the other
thread branch though, I'm a bit skeptical that either of these types
would be useful for a dynamic moving cast -- dynamic cast yes, moving
yes, but both at once is very peculiar semantics.

It's shared_ptr that you need internal access for, if you want to be
able to avoid the refcount changes completely. And this one is more
likely to be useful for dynamic moving casts, though it's still hard to
think of a motivating case.

> For std::shared_ptr and the other pointers we might still emulate a
> moving cast in order to facilitate generic programming.

I'm not sure emulation is any better than existing dynamic_pointer_cast;
this was my attempt:

template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U>&& r) noexcept
{
     T * p = dynamic_cast<T*>(r.get());
     return p ? shared_ptr<T>(r, p) : nullptr;
}

... which looks pretty identical to the non-rvalue dynamic_pointer_cast
to me. I don't really see any opportunities for moving r in this
implementation (without adding an extra constructor to shared_ptr), but
maybe I've missed something.

OTOH, adding this constructor to the Boost version:

template< class Y >
shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_NOEXCEPT
   : px( p ), pn( move(r.pn) )
{
}

(or similar, I haven't tested that) would allow the above to use
shared_ptr<T>(move(r), p), which would be a potential improvement. But
this doesn't help for std::shared_ptr.


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