Re: Barry Revzin's comment, your right, I should probably have iterated a use case.
This was in relation to some code that entailed a checked downcast on a std::unique_ptr, something that is available for shared_ptr but absent in the case of unique_ptr. This would specifically involve dynamic_pointer_cast, but I decided to add the other two (notably omitting reinterpret_pointer_cast, because that is probably more of a footgun then regular reinterpret_cast, if one can believe that is possible). 

On Sun, Dec 27, 2020 at 23:53 Arthur O'Dwyer via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Sun, Dec 27, 2020 at 10:16 PM connor horman via Std-Proposals <std-proposals@lists.isocpp.org> 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:
and on Godbolt:
(Lénárd, have you written a paper for this proposal yet? Shouldn't you, or someone, do that?)
This wouldn't constrain it, it would actually widen it, by allowing explicit construction in any of the cases one of the respective conversions is defined (I don't believe you can have a unique_ptr<void> but you can correct me on that), with one exception, that the case for dynamic_cast across hierarchies is valid only when the destination type has a virtual destructor. 


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.
REBIND_DELETER is designed to work similar to rebind for allocator_traits or for pointer_traits, the same as the original Deleter, but "rebound" to U. 
However, it may be reasonable to constrain the conversions (particularily dynamic_pointer_cast) to std::default_deleter (which, if the conversion suceeds, under the rules I provided, would always have defined behaviour). It may be possible to work with this design, though with some constraints. Certainly in a generic case, you could not rely the reverse dynamic_cast working properly, though for a standard delete t; (ie. with default_deleter) it would work fine anyways (provided A has a virtual destructor). I believe it would also work with allocators, using dynamic_cast<void*>(p), then deallocating that (would a pseudo-destructor call invoke the virtual destructor in the Most-derived object?). In either case, it should 100% work for default_deleter.

I'm wondering if a similar issue could be present with the shared_ptr overloads that already exist in the standard. 

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:
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.
Perhaps, though, as mentioned, these are existing functions in the standard, so the name have precedent, I'm just adding overloads for the unique_ptr case. 

–Arthur
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals