C++ Logo

std-proposals

Advanced search

Remove unsafe conversions of std::default_delete

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Thu, 29 Oct 2020 18:12:33 +0000
Hi,

Consider the following code:

#include <memory>

```
struct Base {};
struct Derived : Base {};

void foo() {
   std::unique_ptr<Base> ptr = std::make_unique<Derived>();
}
```

Calling `foo` is undefined behavior, since Base doesn't have a virtual
destructor. No compiler seems to warn https://godbolt.org/z/xM53P5.

In fact these kind of misusage of unique_ptr could be detected and
disallowed at the point of conversion, if std::default_delete didn't
have a too generous converting constructor template.

_Proposal_

Limit std::default_delete's converting constructor template to only
participate in overload resolution when it's safe to delete the
resulting pointer.

Possible implementation:

template <class T>
struct default_delete {
    constexpr default_delete() noexcept = default;

    template <std::convertible_to<T> U>
    requires (std::derived_from<U, T>
              && std::has_virtual_destructor_v<T>)
             || std::same_as<std::remove_cv_t<U>, std::remove_cv_t<T>>
    default_delete(const default_delete<U>&) noexcept {}

    void operator()(T* ptr) const
    requires requires{ sizeof(T); }
    {
        delete ptr;
    }
};

_Impact on writing code_

After the removal if users don't use unique_ptr's pointer constructors
or its `reset()` member function they can be sure that the call to
~unique_ptr() will not result in UB.

I plan to write this paper after I get some feedback. I got
positive comments on the cpplang slack.

Regards,
Lénárd Szolnoki

Received on 2020-10-29 13:12:43