Title
Incorrect Postconditions on unique_ptr move assignment
Status
c++23
Section
[unique.ptr.single.asgn]
Submitter
Howard Hinnant

Created on 2020-06-22.00:00:00 last changed 13 months ago

Messages

Date: 2020-11-09.21:40:50

Proposed resolution:

This wording is relative to N4861.

  1. Modify [unique.ptr.single.asgn] as indicated:

    unique_ptr& operator=(unique_ptr&& u) noexcept;
    

    -1- Constraints: is_move_assignable_v<D> is true.

    -2- Preconditions: If D is not a reference type, D meets the Cpp17MoveAssignable requirements (Table [tab:cpp17.moveassignable]) and assignment of the deleter from an rvalue of type D 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 type D does not throw an exception.

    -3- Effects: Calls reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).

    -4- Returns: *this.

    -5- Postconditions: If this != addressof(u), u.get() == nullptr, otherwise u.get() is unchanged.

Date: 2020-11-09.00:00:00

[ 2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP. ]

Date: 2020-06-15.00:00:00

[ 2020-06-26; Reflector prioritization ]

Set priority to 0 and status to Tentatively Ready after seven votes in favor during reflector discussions.

Date: 2020-06-22.00:00:00

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

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2020-11-09 21:40:50adminsetmessages: + msg11580
2020-11-09 21:40:50adminsetstatus: ready -> wp
2020-06-26 11:49:53adminsetmessages: + msg11346
2020-06-26 11:49:53adminsetstatus: new -> ready
2020-06-22 13:21:17adminsetmessages: + msg11343
2020-06-22 00:00:00admincreate