Search code examples
c++unique-ptrnoexceptexception-safety

Why std::unique_ptr does not explicitly require a noexcept Deleter?


The documentation says that Deleter should be:

  • nothrow constructible
  • nothrow callable (because it's called from ~unique_ptr() noexcept
  • nothrow destructible (for the reason above)

My question is why uniqut_ptr is defined to allow a Deleter that may throw. E.g. the following Deleter is allowed by all unique_ptr constructors:

struct BadDeleter
{
    BadDeleter() noexcept(false) {}
    ~BadDeleter() noexcept(false) {}
    BadDeleter(const BadDeleter&) noexcept(false) {}
    BadDeleter(BadDeleter&) noexcept(false) {}
    BadDeleter(BadDeleter&&) noexcept(false) {}
    void operator()(char* p) const noexcept(false) {
        delete p;
    };
};

Live Demo


Solution

  • The standard only defines the requirements on a uniqe_ptr's deleter based on the unique_ptr's operations. While those requirements always say things like

    ~unique_ptr();
    Requires: The expression get_deleter()(get()) shall be well formed, shall have well-defined behavior, and shall not throw exceptions.

    the standard never explicitly specifies that the deleter must have a noexcept operator().

    I presume this wording was chosen to remain backwards-compatible with C++14. In that standard, noexcept was not part of a function's signature, and adding that requirement in C++17 likely would have broken a lot of code where custom deleters were used without explicitly marking their operations as noexcept.