Date: Wed, 28 Jul 2021 11:46:52 -0400
On Wed, Jul 28, 2021 at 10:31 AM Bjorn Reese via Std-Discussion
<std-discussion_at_[hidden]> wrote:
>
> The move constructor and move assignment of std::promise in does not
> mention the effects on associated futures when a promise is reassigned.
>
> Consider the following code:
>
> #include <future>
>
> int main()
> {
> std::promise<int> promise;
> auto result = promise.get_future();
> promise = decltype(promise){}; // Reassigned
> promise.set_value(1);
> return result.get();
> }
>
> In this case I would expect the future to be notified about a broken
> promise, just as if the promise had been destroyed.
>
> The code above gives different results for the main standard library
> implementations.
>
> * libc++ throws a broken promise exception from future::get().
> * libstdc++ throws an accidental and unknown exception from
> promise::set_value().
> * MSVC returns 0.
>
> The behaviour can be made consistent by changing [future.promise] from
>
> promise(promise&& rhs) noexcept;
> Effects: Transfers ownership of the shared state of rhs (if any)
> to the newly-constructed object.
>
> into
>
> promise(promise&& rhs) noexcept;
> Effects: Abanons any shared state (32.9.5) and then transfers
> ownership of the shared state of rhs (if any) to the newly-
> constructed object.
>
> Should I report this as an LWG defect?
That's the move *constructor*. When you're constructing an object,
there is no state to abandon. Also, the problem in your example code
never move-constructs anything. It creates a temporary, then
move-assigns it to the `promise` variable (BTW, don't give the
variable of type `promise` the name `promise`. It's needlessly
confusing).
The problem as you have outlined it comes from move-*assignment*, not
move-construction. And move assignment already uses that wording
(though it should have a carveout for self-move-assignment).
There is no defect here, just some poor implementations.
<std-discussion_at_[hidden]> wrote:
>
> The move constructor and move assignment of std::promise in does not
> mention the effects on associated futures when a promise is reassigned.
>
> Consider the following code:
>
> #include <future>
>
> int main()
> {
> std::promise<int> promise;
> auto result = promise.get_future();
> promise = decltype(promise){}; // Reassigned
> promise.set_value(1);
> return result.get();
> }
>
> In this case I would expect the future to be notified about a broken
> promise, just as if the promise had been destroyed.
>
> The code above gives different results for the main standard library
> implementations.
>
> * libc++ throws a broken promise exception from future::get().
> * libstdc++ throws an accidental and unknown exception from
> promise::set_value().
> * MSVC returns 0.
>
> The behaviour can be made consistent by changing [future.promise] from
>
> promise(promise&& rhs) noexcept;
> Effects: Transfers ownership of the shared state of rhs (if any)
> to the newly-constructed object.
>
> into
>
> promise(promise&& rhs) noexcept;
> Effects: Abanons any shared state (32.9.5) and then transfers
> ownership of the shared state of rhs (if any) to the newly-
> constructed object.
>
> Should I report this as an LWG defect?
That's the move *constructor*. When you're constructing an object,
there is no state to abandon. Also, the problem in your example code
never move-constructs anything. It creates a temporary, then
move-assigns it to the `promise` variable (BTW, don't give the
variable of type `promise` the name `promise`. It's needlessly
confusing).
The problem as you have outlined it comes from move-*assignment*, not
move-construction. And move assignment already uses that wording
(though it should have a carveout for self-move-assignment).
There is no defect here, just some poor implementations.
Received on 2021-07-28 10:47:09