Created on 2024-08-30.00:00:00 last changed 3 weeks ago
Proposed resolution:
This wording is relative to N4988.
Modify [unique.ptr.single.general] as indicated:
-?- A program that instantiates the definition of
unique_ptr<T, D>
is ill-formed if `T*` is an invalid type.
[Note: This prevents the intantiation of specializations such asunique_ptr<T&, D>
andunique_ptr<int() const, D>
. — end note]-1- The default type for the template parameter `D` is `default_delete`. A client-supplied template argument `D` shall be a function object type ([function.objects]), 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.-2- If the deleter’s type `D` is not a reference type, `D` shall meet the Cpp17Destructible requirements (Table 35).
-3- If the qualified-id
remove_reference_t<D>::pointer
is valid and denotes a type ([temp.deduct]), thenunique_ptr<T, D>::pointer
shall be a synonym forremove_reference_t<D>::pointer
. Otherwiseunique_ptr<T, D>::pointer
shall be a synonym forelement_type*
. The typeunique_ptr<T, D>::pointer
shall meet the Cpp17NullablePointer requirements (Table 36).-4- [Example 1: Given an allocator type `X` ([allocator.requirements.general]) and letting `A` be a synonym for
allocator_traits<X>
, the types `A::pointer`, `A::const_pointer`, `A::void_pointer`, and `A::const_void_pointer` may be used asunique_ptr<T, D>::pointer
. — end example]
[ Wrocław 2024-11-23; Status changed: Voting → WP. ]
[ 2024-11-13; Reflector poll ]
Set status to Tentatively Ready after eight votes in favour during reflector poll.
It seems that we currently allow nonsensical specializations of `unique_ptr`
such as unique_ptr<int&, D>
and unique_ptr<void()const, D>
(a custom deleter that defines `D::pointer` is needed, because otherwise
the `pointer` type would default to invalid types like
int&*
or void(*)()const
).
There seems to be no reason to support these "unique pointer to reference"
and "unique pointer to abominable function type" specializations,
or any specialization for a type that you couldn't form a raw pointer to.
Prior to C++17, the major library implementations rejected such specializations
as a side effect of the constraints for the
unique_ptr(auto_ptr<U>&&)
constructor
being defined in terms of is_convertible<U*, T*>
.
This meant that overload resolution for any constructor of `unique_ptr`
would attempt to form the type `T*` and fail if that was invalid.
With the removal of `auto_ptr` in C++17, that constructor was removed
and now unique_ptr<int&, D>
can be instantiated
(assuming any zombie definition of `auto_ptr` is not enabled by the library).
This wasn't intentional, but just an accident caused by not explicitly
forbidding such types.
Discussion on the LWG reflector led to near-unanimous support for explicitly disallowing these specializations for non-pointable types.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-11-28 21:40:31 | admin | set | messages: + msg14492 |
2024-11-28 21:40:31 | admin | set | status: voting -> wp |
2024-11-19 16:09:07 | admin | set | status: ready -> voting |
2024-11-13 20:38:33 | admin | set | messages: + msg14450 |
2024-11-13 20:38:33 | admin | set | status: new -> ready |
2024-08-31 14:11:41 | admin | set | messages: + msg14348 |
2024-08-30 00:00:00 | admin | create |