Title
§[unique.ptr.single] requirements on deleter may be too strict
Status
new
Section
[unique.ptr.single]
Submitter
Jonathan Wakely

Created on 2018-09-17.00:00:00 last changed 74 months ago

Messages

Date: 2018-10-06.10:50:02

[ 2018-10 Reflector prioritization ]

Set Priority to 3

Date: 2018-09-17.00:00:00

[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>.

History
Date User Action Args
2018-10-06 10:50:02adminsetmessages: + msg10157
2018-09-17 00:00:00admincreate