This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
unique_ptr
move assignmentSection: 20.3.1.3.4 [unique.ptr.single.asgn] Status: C++23 Submitter: Howard Hinnant Opened: 2020-06-22 Last modified: 2023-11-22
Priority: 0
View all other issues in [unique.ptr.single.asgn].
View all issues with C++23 status.
Discussion:
20.3.1.3.4 [unique.ptr.single.asgn]/p5 says this about the unique_ptr
move assignment operator:
Postconditions:
u.get() == nullptr
.
But this is only true if this != &u
. For example:
#include <iostream> #include <memory> int main() { auto x = std::unique_ptr<int>(new int{3}); x = std::move(x); if (x) std::cout << *x << '\n'; else std::cout << "nullptr\n"; }
Output:
3
An alternative resolution to that proposed below is to just delete the Postcondition altogether as the Effects element completely specifies everything. If we do that, then we should also remove p10, the Postconditions element for the converting move assignment operator. I have a slight preference for the proposed change below as it is more informative, at the expense of being a little more repetitive.
[2020-06-26; Reflector prioritization]
Set priority to 0 and status to Tentatively Ready after seven votes in favor during reflector discussions.
[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]
Proposed resolution:
This wording is relative to N4861.
Modify 20.3.1.3.4 [unique.ptr.single.asgn] as indicated:
unique_ptr& operator=(unique_ptr&& u) noexcept;-1- Constraints:
-2- Preconditions: Ifis_move_assignable_v<D>
istrue
.D
is not a reference type,D
meets the Cpp17MoveAssignable requirements (Table [tab:cpp17.moveassignable]) and assignment of the deleter from an rvalue of typeD
does not throw an exception. Otherwise,D
is a reference type;remove_reference_t<D>
meets the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of typeD
does not throw an exception. -3- Effects: Callsreset(u.release())
followed byget_deleter() = std::forward<D>(u.get_deleter())
. -4- Returns:*this
. -5- Postconditions: Ifthis != addressof(u)
,u.get() == nullptr
, otherwiseu.get()
is unchanged.