Boost logo

Boost :

Subject: Re: [boost] [smart_ptr] Is there any interest in unique_ptr with type erased deleter?
From: Richard Hodges (hodges.r_at_[hidden])
Date: 2017-03-21 14:32:24


Re-posting here as I replied direct to Andrey by mistake:

> May be the best solution will be implement type_erased_unique_ptr
publicly inheriting from std::unique_ptr<T, type_erased_deleter> and
defining own set of constructors. What do you think about this?

I think that's reasonable. The conversion constructor can take care of
marshalling the pointer and deleter into the polymorphic deleter.

Again though, is this necessary? Won't a partial specialisation take care
of this? The c++ standard mandates that specialisations of std:: template
classes must provide the services specified at a *minimum*. It does not
prevent them from offering more services (such as a conversion constructor).

By which I mean, this is legal, AFAIK:

namespace std {

    template<class T>
    struct unique_ptr<T, ::notstd::polymorphic_deleter>
    {
        template<class U, class D, std::enable_if_t<not
std::is_same<D, ::notstd::polymorphic_deleter>::value>* = nullptr>
            unique_ptr(std::unique_ptr<U, D>&& other)
        {
            // ...
        }

        // etc... implement the rest of unique_ptr's interface
    };
}

On 21 March 2017 at 12:54, Andrey Davydov via Boost <boost_at_[hidden]>
wrote:

> On Tue, Mar 21, 2017 at 2:15 PM, Andrey Semashev via Boost <
> boost_at_[hidden]> wrote:
>
> > On 03/21/17 12:54, Andrey Davydov via Boost wrote:
> >
> >> On Tue, Mar 21, 2017 at 12:00 PM, Richard Hodges <hodges.r_at_[hidden]>
> >> wrote:
> >>
> >> What is required, more than simply creating a type-erased deleter?
> >>>
> >>
> >> Also deleter must capture pointer, because pointer which was passed to
> >> constructor can differ from the pointer which will be deleted. For
> >> example,
> >>
> >> struct Base { /* ... */ };
> >> struct Derived : Base { /* ... */ };
> >>
> >> ptr<Derived> p1(new Derived);
> >> void * raw_p1 = p1.get();
> >> ptr<Base> p2 = std::move(p1);
> >> void * raw_p2 = p2.get();
> >> assert(raw_p1 != raw_p2);
> >>
> >
> > The above piece of code strikes me as very unsafe and better be avoided
> in
> > the first place. Designing new tools to handle this case is IMHO
> misguided.
> >
> Why this code is very unsafe? If change `ptr` to `shared_ptr` this will
> become perfectly valid and widely used pattern.
>
> >
> > Now, I can understand the need to perform casts on smart-pointers, but
> > they should still provide some level of safety, at least the same level
> > that is provided by pointer casts in the core language. But supporting
> > casts should not require a new smart-pointer. And indeed it doesn't:
> >
> > template< typename U, typename T, typename D >
> > std::unique_ptr< U, D > static_pointer_cast(
> > std::unique_ptr< T, D >&& p)
> > {
> > D d = p.get_deleter();
> > return std::unique_ptr< U, D >(
> > static_cast< U* >(p.release()),
> > std::move(d));
> > }
> >
> What is `D`? If it is std::default_delete<T> then function result type will
> be std::unique_ptr<U, std::default_delete<T>> and unlikely this type is
> very useful (even if it compiles).
>
>
> > The other part of your proposal, which is polymorphic behavior with a
> > deleter knowing the type to call the destructor on, can be solved by a
> > custom deleter. I'm not sure a generalized version of such deleter would
> > have a large demand, given that there is the alternative TONGARI J
> > suggested, but I'm not opposed to a proposal.
>
> May be I doesn't understand what TONGARI J suggested, but how can
> `unique_ptr<T,
> void(*)(T*)>` hold stateful deleter?
>
> --
> Andrey Davydov
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/
> mailman/listinfo.cgi/boost
>


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