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.Dis not a reference type,Dmeets the Cpp17MoveAssignable requirements (Table [tab:cpp17.moveassignable]) and assignment of the deleter from an rvalue of typeDdoes not throw an exception. Otherwise,Dis a reference type;remove_reference_t<D>meets the Cpp17CopyAssignable requirements and assignment of the deleter from an lvalue of typeDdoes 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.