This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

### 3795. Self-move-assignment of `std::future` and `std::shared_future` have unimplementable postconditions

Section: 33.10.7 [futures.unique.future], 33.10.8 [futures.shared.future] Status: WP Submitter: Jiang An Opened: 2022-10-19 Last modified: 2022-11-17

Priority: 3

View all other issues in [futures.unique.future].

View all issues with WP status.

Discussion:

The move assignment operators of `std::future` and `std::shared_future` have their postconditions specified as below:

> Postconditions:

> - `valid()` returns the same value as `rhs.valid()` returned prior to the assignment.

> - `rhs.valid() == false`.

It can be found that when `*this` and `rhs` is the same object and `this->valid()` is `true` before the assignment, the postconditions can't be achieved.

Mainstream implementations (libc++, libstdc++, msvc stl) currently implement such self-move-assignment as no-op, which doesn't meet the requirements in the Effects: element. As discussed in LWG 3788, I think we should say self-move-assignment has no effects for these types.

[2022-11-01; Reflector poll]

Set priority to 3 after reflector poll.

[2022-11-01; Jonathan provides wording]

[2022-11-07; Reflector poll]

Set status to Tentatively Ready after six votes in favour during reflector poll.

[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4917.

1. Modify 33.10.7 [futures.unique.future] as indicated:

   > >     future& operator=(future&& rhs) noexcept;

   > > -11- Effects: If `addressof(rhs) == this` is `true`, there are no effects. Otherwise:

   > > 1. (11.1) — Releases any shared state (33.10.5 [futures.state]).
   > > 2. (11.2) — move assigns the contents of `rhs` to `*this`.

   > > -12- Postconditions:

   > > 1. (12.1) — `valid()` returns the same value as `rhs.valid()` prior to the assignment.
   > > 2. (12.2) — If `addressof(rhs) == this` is `false`, `rhs.valid() == false`.

2. Modify 33.10.8 [futures.shared.future] as indicated:

   > >     shared_future& operator=(shared_future&& rhs) noexcept;

   > > -13- Effects: If `addressof(rhs) == this` is `true`, there are no effects. Otherwise:

   > > 1. (13.1) — Releases any shared state (33.10.5 [futures.state]).
   > > 2. (13.2) — move assigns the contents of `rhs` to `*this`.

   > > -14- Postconditions:

   > > 1. (14.1) — `valid()` returns the same value as `rhs.valid()` returned prior to the assignment.
   > > 2. (14.2) — If `addressof(rhs) == this` is `false`, `rhs.valid() == false`.

   > >     shared_future& operator=(const shared_future& rhs) noexcept;

   > > -15- Effects: If `addressof(rhs) == this` is `true`, there are no effects. Otherwise:

   > > 1. (15.1) — Releases any shared state (33.10.5 [futures.state]).
   > > 2. (15.2) — assigns the contents of `rhs` to `*this`.

   > >    [Note 3: As a result, `*this` refers to the same shared state as `rhs` (if any). — end note]

   > > -16- Postconditions: `valid() == rhs.valid()`.