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.
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
isdefault_delete
. A client-supplied template argumentD
shall be a function object type (19.14), lvalue reference to function, or lvalue reference to function object type for which, given a valued
of typeD
and a value ptr of typeunique_ptr<T, D>::pointer
, the expressiond(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(i) etc).
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: