Created on 2025-02-03.00:00:00 last changed 2 months ago
Proposed resolution:
This wording is relative to N5001.
-8- Let `Sigs` be a pack of the arguments to the `completion_signatures` specialization named by
completion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>
. Letas-tuple
be an alias templatethat transforms a completion signature `Tag(Args...)` into the tuple specializationsuch thatdecayed-tuple<Tag, Args...>
.as-tuple<Tag(Args...)>
denotes the typedecayed-tuple<Tag, Args...>
, and letis-nothrow-decay-copy-sig
be a variable template such thatauto(is-nothrow-decay-copy-sig<Tag(Args...)>)
is a constant expression of type `bool` and equal to(is_nothrow_constructible_v<decay_t<Args>, Args> && ...)
. Leterror-completion
be a pack consisting of the type `set_error_t(exception_ptr)` if(is-nothrow-decay-copy-sig<Sigs> &&...)
is `false`, and an empty pack otherwise. Then `variant_t` denotes the typevariant<monostate, as-tuple<Sigs>..., error-completion...>
, except with duplicate types removed.
Modify [exec.schedule.from] p11 as indicated:
-11- The member
impls-for<schedule_from_t>::complete
is initialized with a callable object equivalent to the following lambda:[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept -> void { using result_t = decayed-tuple<Tag, Args...>; constexpr bool nothrow =
is_nothrow_constructible_v<result_t, Tag, Args...>(is_nothrow_constructible_v<decay_t<Args>, Args> && ...); try { state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...); } catch (...) { if constexpr (!nothrow){state.async-result.template emplace<tuple<set_error_t, exception_ptr>>(set_error, current_exception());set_error(std::move(rcvr), current_exception());return;}} start(state.op-state); };
[ Hagenberg 2025-02-12; move to Ready ]
[ 2025-02-12 Tim adds PR ]
This also corrects the issue that `nothrow` is currently relying on the unspecified exception specification of `tuple`'s constructor.
[ Hagenberg 2025-02-11; LWG ]
Direction seems right. Decay-copyable is not a defined term.
[ 2025-02-07; Reflector poll ]
Set priority to 1 after reflector poll.
[ This touches the same text as LWG 4203. ]
Imported from cplusplus/sender-receiver #304.
[exec.schedule.from]/p11 specifies `schedule_from`'s completion operation as follows:
[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
-> void {
using result_t = decayed-tuple<Tag, Args...>;
constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>;
try {
state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
} catch (...) {
if constexpr (!nothrow) {
set_error(std::move(rcvr), current_exception());
return;
}
}
start(state.op-state);
};
so if emplacing the result tuple throws, `set_error` is immediately called on the downstream receiver. no attempt is made to post the completion to the specified scheduler. this is probably not the right behavior.
Suggested resolution
The right thing, i think, is to catch the exception, emplace the `exception_ptr` into the `async-result` variant, and then start the schedule operation, as shown below:
[]<class Tag, class... Args>(auto, auto& state, auto& rcvr, Tag, Args&&... args) noexcept
-> void {
using result_t = decayed-tuple<Tag, Args...>;
constexpr bool nothrow = is_nothrow_constructible_v<result_t, Tag, Args...>;
try {
state.async-result.template emplace<result_t>(Tag(), std::forward<Args>(args)...);
} catch(...) {
if constexpr (!nothrow)
state.async-result.template emplace<tuple<set_error_t, exception_ptr>>(set_error, current_exception());
}
start(state.op-state);
}
we also need to change how we specify the variant type of
state.async-result
:
Let `Sigs` be a pack of the arguments to the `completion_signatures` specialization named bycompletion_signatures_of_t<child-type<Sndr>, env_of_t<Rcvr>>
. Letas-tuple
be an alias templatethat transforms a completion signature `Tag(Args...)` into the tuple specializationsuch thatdecayed-tuple<Tag, Args...>
.as-tuple<Tag(Args...)>
denotes the tuple specializationdecayed-tuple<Tag, Args...>
, and letis-nothrow-decay-copy-sig
be a variable template such thatis-nothrow-decay-copy-sig<Tag(Args...)>
is a core constant expression of type `bool const` and whose value is `true` if the types `Args...` are all nothrow decay-copyable, and `false` otherwise. Leterror-completion
be a pack consisting of the type `set_error_t(exception_ptr)` if(is-nothrow-decay-copy-sig<Sigs> &&...)
is `false`, and an empty pack otherwise. Then `variant_t` denotes the typevariant<monostate, as-tuple<Sigs>..., error-completion...>
, except with duplicate types removed.
History | |||
---|---|---|---|
Date | User | Action | Args |
2025-02-13 17:25:31 | admin | set | messages: + msg14640 |
2025-02-13 17:25:31 | admin | set | status: new -> ready |
2025-02-12 06:38:49 | admin | set | messages: + msg14639 |
2025-02-12 06:38:49 | admin | set | messages: + msg14638 |
2025-02-11 15:11:16 | admin | set | messages: + msg14631 |
2025-02-07 22:17:52 | admin | set | messages: + msg14610 |
2025-02-03 16:56:11 | admin | set | messages: + msg14563 |
2025-02-03 00:00:00 | admin | create |