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.

### 2697. [concurr.ts] Behavior of `future/shared_future` unwrapping constructor when given an invalid `future`

Section: 99 [concurr.ts::futures.unique_future], 99 [concurr.ts::futures.shared_future] Status: WP Submitter: Tim Song Opened: 2016-04-22 Last modified: 2021-02-27

Priority: 2

View all issues with WP status.

Discussion:

Addresses: concurr.ts

In the concurrency TS, the future/shared_future unwrapping constructors

>     future(future<future<R>>&&) noexcept;
>     shared_future(future<shared_future<R>>&& rhs) noexcept;

appear to implicitly require `rhs` be valid (e.g., by referring to its shared state, and by requiring a `valid() == true` postcondition). However, they are also marked `noexcept`, suggesting that they are wide-contract, and also makes the usual suggested handling for invalid futures, throwing a `future_error`, impossible.

Either the `noexcept` should be removed, or the behavior with an invalid future should be specified.

Original resolution alternative #1 [NOT CHOSEN]:

> This wording is relative to N4577.

> Strike the `noexcept` on these constructors in 99 [concurr.ts::futures.unique_future]/1-2 and 99 [concurr.ts::futures.shared_future]/1-2, and optionally add a Requires: `rhs.valid() == true` paragraph.

[2016-11-12, Issaquah]

Sat PM: We prefer alternative #2 - Move to review

[2018-06; Rapperswil, Wednesday evening session]

DR: there is a sentence ended followed by an entirely new sentence
JM: so the period should be a semicolon in both edits
MC: ACTION I can make the change editorially
ACTION move to Ready

[2018-11, Adopted in San Diego]

Proposed resolution:

This wording is relative to N4577.

> Alternative #2: Specify that an empty (`shared_`)`future` object is constructed if `rhs` is invalid, and adjust the postcondition accordingly.

1. Edit 99 [concurr.ts::futures.unique_future] as indicated:

   >     future(future<future<R>>&& rhs) noexcept;

   > > -3- Effects: If `rhs.valid() == false`, constructs an empty `future` object that does not refer to a shared state. Otherwise, c Constructs a `future` object from the shared state referred to by `rhs`. T; the `future` becomes ready when one of the following occurs:

   > > - Both the `rhs` and `rhs.get()` are ready. The value or the exception from `rhs.get()` is stored in the `future`'s shared state.

   > > - `rhs` is ready but `rhs.get()` is invalid. An exception of type `std::future_error`, with an error condition of `std::future_errc::broken_promise` is stored in the `future`'s shared state.

   > > -4- Postconditions:

   > > - `valid() == true` `valid()` returns the same value as `rhs.valid()` prior to the constructor invocation..

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

2. Edit 99 [concurr.ts::futures.shared_future] as indicated:

   >     shared_future(future<shared_future<R>>&& rhs) noexcept;

   > > -3- Effects: If `rhs.valid() == false`, constructs an empty `shared_future` object that does not refer to a shared state. Otherwise, c Constructs a `shared_future` object from the shared state referred to by `rhs`. T; the `shared_future` becomes ready when one of the following occurs:

   > > - Both the `rhs` and `rhs.get()` are ready. The value or the exception from `rhs.get()` is stored in the `shared_future`'s shared state.

   > > - `rhs` is ready but `rhs.get()` is invalid. The `shared_future` stores an exception of type `std::future_error`, with an error condition of `std::future_errc::broken_promise`.

   > > -4- Postconditions:

   > > - `valid() == true` `valid()` returns the same value as `rhs.valid()` prior to the constructor invocation..

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