This paper proposes a resolution to C++17 CD comment GB 62, which addresses
operations on shared_future which have wide contracts.
1. GB 62
There is an implicit precondition on mostshared_futureoperations thatvalid() == true, 30.6.7p3. The list of exempted functions seems copied directly from classfuture, and would also include copy operations forshared_futures, which are copyable. Similarly, this would be a wide contract that cannot throw, so those members would be markednoexcept.
2. SG1 and LEWG Response to GB 62
SG1 agreed with the proposed wording in the NB comment for shared_future.
They felt the move constructor should also be added for the list in future as well. There was unanimous consent to forward this paper to LEWG for design
review. LEWG reviewed it and sent it to LWG.
3. LWG Feedback
LWG made the following changes:
-
Rejected the addition of the constructors from the pre-condition whitelist (as the precondition has no meaning before the object is constructed).
-
Added a note clarifying that it is valid to copy from a future for which
valid()isfalse.
There was unanimous consent in LWG to move this paper at the Issaquah 2016 Friday plenary.
4. Proposed Wording
The proposed changes are relative to [N4604], the Committee Draft for C++17.
4.1. Changes to shared_future
Apply the following changes to 30.6.7 [futures.shared_future] paragraph 3:
The effect of calling any member function other than the destructor, the move-assignment operator, the copy-assignment operator, orvalidon ashared_futureobject for whichvalid()isfalseis undefined. [ Note: It is valid to copy or move from ashared_futureobject for whichvalid()isfalse— end note ] [ Note: Implementations are encouraged to detect this case and throw an object of typefuture_errorwith an error condition offuture_errc::no_state. — end note ]
Apply the following changes to the class synopsis for shared_future in
30.6.7 [futures.shared_future]:
namespace std { template <class R> class shared_future { public: shared_future() noexcept; shared_future(const shared_future& rhs) noexcept; shared_future(future<R>&&) noexcept; shared_future(shared_future&& rhs) noexcept; ~shared_future(); shared_future& operator=(const shared_future& rhs) noexcept; shared_future& operator=(shared_future&& rhs) noexcept; // retrieving the value see below get() const; // functions to check state bool valid() const noexcept; void wait() const; template <class Rep, class Period> future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const; template <class Clock, class Duration> future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const; }; }
Apply the following changes to the definition of shared_future's copy
constructor in 30.6.7 [futures.shared_future]:
shared_future(const shared_future& rhs) noexcept;Effects: Constructs a
shared_futureobject that refers to the same shared state asrhs(if any).Postcondition:
valid()returns the same value asrhs.valid().
Apply the following changes to the definition of shared_future's copy
assignment operator in 30.6.7 [futures.shared_future]:
shared_future& operator=(const shared_future& rhs) noexcept;Effects:
Releases any shared state (30.6.4);
assigns the contents of
rhsto*this. [ Note: As a result,*thisrefers to the same shared state asrhs(if any). — end note ]Postconditions:
valid() == rhs.valid().
4.2. Changes to future
Apply the following changes to 30.6.6 [futures.unique_future] paragraph 3:
The effect of calling any member function other than the destructor, the move-assignment operator, orvalidon afutureobject for whichvalid()isfalseis undefined. [ Note: It is valid to move from afutureobject for whichvalid() == false— end note ]
4.3. Acknowledgements
Thanks to Jonathan Wakely for assisting with the wording.