C++ Logo

std-proposals

Advanced search

Re: pointer_cast for unique_ptr

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Sun, 27 Dec 2020 23:52:44 -0500
On Sun, Dec 27, 2020 at 10:16 PM connor horman via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> To std::default_deleter<T> [...] modify the constructor of default_deleter
> to participate in overload resolution if any of the following is true:
> - U is a (possibly virtual) base class of T (does this need to allow
> inaccessible base classes, or is that not permitted by an implicit
> conversion),
> - T is an accessible (possibly virtual) base class of U, in a context
> unrelated to both T and U,
> - U is (possibly-differently cv-qualified) T, or
> - Both T and U are polymorphic types and U has a virtual destructor.
>

This part sounds like Lénárd Szolnoki's proposal for further constraining
constructors of default_delete. I've got an implementation of it here:
https://github.com/Quuxplusone/llvm-project/commit/ec526c22aa43954d35356f63b55867c16aa08e88
and on Godbolt:
https://p1144.godbolt.org/z/hEYz6c
(Lénárd, have you written a paper for this proposal yet? Shouldn't you, or
someone, do that?)


> template<typename U,typename T,typename D>
> std::unique_ptr<U,REBIND_DELETER<D,U>>
> dynamic_pointer_cast(std::unique_ptr<T,D>&& ptr)
> - Performs a type qualification conversion of a unique_ptr, as though by
> const_cast
> - Only participates in overload resolution if REBIND_DELETER<D,U> is well
> formed and constructible from D,
> typename std::pointer_traits<typename D::pointer>::template rebind<U> is
> implicitly convertible to typename REBIND_DELETER<D,U>::pointer, the
> conversion from T* to U* may be performed by a valid dynamic_cast
>

I haven't tried to decipher your REBIND_DELETER stuff, but I suspect that
you're going to have trouble with the fact that dynamic_cast is not
reversible: it's quite possible to have an A *a1, dynamic_cast it to a B*,
dynamic_cast the B* back to an A*, and end up with a completely different
object! So if your strategy is to return a unique_ptr<B, SomeDeleter> with
a deleter that dynamic_casts B* back to A* and deletes that with the
original deleter... well, that's not going to work the way you wanted.
https://godbolt.org/z/Y376Kr

In real code, I'd want to see a function named clearly after its purpose,
e.g. `ptr_downcast` if you want to use it for downcasts within a hierarchy:
https://godbolt.org/z/abG33b
If I saw someone trying to do this in the presence of a custom deleter,
and/or via a generically named function like `static_pointer_cast`, I'd bet
that they didn't know what they were doing.

–Arthur

Received on 2020-12-27 22:52:57