This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
connect-awaitable should use is_void_v to check for result-type of
co_await expression instead of same_as<void>Section: 33.9.10 [exec.connect] Status: New Submitter: Lewis Baker Opened: 2025-08-27 Last modified: 2025-10-23
Priority: 4
View other active issues in [exec.connect].
View all other issues in [exec.connect].
View all issues with New status.
Discussion:
The wording in 33.9.10 [exec.connect] p5 defines the connect-awaitable() function as follows:
operation-state-task connect-awaitable(DS sndr, DR rcvr) requires receiver_of<DR, Sigs> {
exception_ptr ep;
try {
if constexpr (same_as<V, void>) {
co_await std::move(sndr);
co_await suspend-complete(set_value, std::move(rcvr));
} else {
co_await suspend-complete(set_value, std::move(rcvr), co_await std::move(sndr));
}
} catch(...) {
ep = current_exception();
}
co_await suspend-complete(set_error, std::move(rcvr), std::move(ep));
}
The use of same_as<V, void> in the if-constexpr condition does not cover the case where the
result of the co_await expression has type cv void. It should use is_void_v<V>
instead to allow it to match all void types, not just unqualified void.
[2025-10-23; Reflector poll.]
Set priority to 4 after reflector poll.
"NAD, V is await-result-type<...> which is decltype(...)
and you never get cv void from decltype (7.2.2 [expr.type] p2)."
"But using is_void_v more clearly expresses the intent."
Proposed resolution:
This wording is relative to N5014.
Modify 33.9.10 [exec.connect] as indicated:
-5- Let
Vname the typeawait-result-type<DS, connect-awaitable-promise>, letSigsname the typecompletion_signatures< SET-VALUE-SIG(V), // see 33.9.3 [exec.snd.concepts] set_error_t(exception_ptr), set_stopped_t()>and let
connect-awaitablebe an exposition-only coroutine defined as follows:namespace std::execution { […] operation-state-task connect-awaitable(DS sndr, DR rcvr) requires receiver_of<DR, Sigs> { exception_ptr ep; try { if constexpr (same_as<V, void>is_void_v<V>) { co_await std::move(sndr); co_await suspend-complete(set_value, std::move(rcvr)); } else { co_await suspend-complete(set_value, std::move(rcvr), co_await std::move(sndr)); } } catch(...) { ep = current_exception(); } co_await suspend-complete(set_error, std::move(rcvr), std::move(ep)); } }