This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3159. §[unique.ptr.single] requirements on deleter may be too strict

Section: 20.3.1.3 [unique.ptr.single] Status: New Submitter: Jonathan Wakely Opened: 2018-09-17 Last modified: 2018-10-06

Priority: 3

View other active issues in [unique.ptr.single].

View all other issues in [unique.ptr.single].

View all issues with New status.

Discussion:

20.3.1.3 [unique.ptr.single] p1 says:

> The default type for the template parameter `D` is `default_delete`. A client-supplied template argument `D` shall be a function object type (19.14), lvalue reference to function, or lvalue reference to function object type for which, given a value `d` of type `D` and a value ptr of type `unique_ptr<T, D>::pointer`, the expression `d(ptr)` is valid and has the effect of disposing of the pointer as appropriate for that deleter.

That means this is undefined:

>     #include <memory>

>     struct IncompleteBase;

>     struct Deleter {
>       void operator()(IncompleteBase*) const;
>     };

>     struct IncompleteDerived;

>     struct X {
>       std::unique_ptr<IncompleteDerived, Deleter> p;
>       ~X();
>     };

`unique_ptr::pointer` is `IncompleteDerived*`, but `is_invocable<Deleter, IncompleteDerived*>` is unknowable until the type is complete (see LWG 3099 etc).

The intention is that `IncompleteDerived` only needs to be complete when the deleter is invoked, which is in the definition of `X::~X()` for this example. But the requirement for `d(ptr)` to be valid requires a complete type. If the `unique_ptr` implementation adds `static_assert(is_invocable_v<D, pointer>)` to enforce the requirement, the example above fails to compile. GCC recently added that assertion.

Do we want to relax that requirement, or do we want to force the code above to define `Deleter::pointer` as `IncompleteBase*` so that the `is_invocable` condition can be checked?

The destructor and `reset` member function already require that the deleter can be invoked (and that Requires: element will be turned into a Mandates: one soon). We can just remove that requirement from the preamble for the class template, or say that the expression only needs to be valid when the destructor and `reset` member are instantiated. We could also rephrase it in terms of `is_invocable_v<D, unique_ptr<T, D>::pointer>`.

[2018-10 Reflector prioritization]

Set Priority to 3

Proposed resolution: