From 84f7ebedb4333043f2c2abc54af8fe4197c12241 Mon Sep 17 00:00:00 2001 From: Cra3z Date: Wed, 23 Sep 2026 17:22:28 +0800 Subject: [PATCH 1/3] Refactor completion-signatures of `let` and `continues_on` --- .../beman/execution/detail/continues_on.hpp | 63 ++++++++------- include/beman/execution/detail/let.hpp | 79 +++++++++++-------- tests/beman/execution/issue-186.test.cpp | 2 +- 3 files changed, 81 insertions(+), 63 deletions(-) diff --git a/include/beman/execution/detail/continues_on.hpp b/include/beman/execution/detail/continues_on.hpp index c5105e04..cac25058 100644 --- a/include/beman/execution/detail/continues_on.hpp +++ b/include/beman/execution/detail/continues_on.hpp @@ -29,6 +29,7 @@ import beman.execution.detail.env; import beman.execution.detail.env_of_t; import beman.execution.detail.error_types_of_t; import beman.execution.detail.fwd_env; +import beman.execution.detail.gather_signatures; import beman.execution.detail.get_completion_domain; import beman.execution.detail.get_completion_scheduler; import beman.execution.detail.get_completion_signatures; @@ -48,9 +49,7 @@ import beman.execution.detail.schedule_result_t; import beman.execution.detail.scheduler; import beman.execution.detail.sender; import beman.execution.detail.sender_adaptor_closure; -import beman.execution.detail.sender_for; import beman.execution.detail.sender_in; -import beman.execution.detail.sends_stopped; import beman.execution.detail.set_error; import beman.execution.detail.set_stopped; import beman.execution.detail.set_value; @@ -66,6 +65,7 @@ import beman.execution.detail.start; #include #include #include +#include #include #include #include @@ -83,9 +83,7 @@ import beman.execution.detail.start; #include #include #include -#include #include -#include #include #include #include @@ -113,6 +111,20 @@ struct continues_on_t { } private: + template + using variant_type = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::prepend< + ::std::monostate, + ::beman::execution::detail::meta::transform< + ::beman::execution::detail::as_tuple_t, + ::beman::execution::detail::meta::to<::std::variant, + ::beman::execution::completion_signatures_of_t>>>>; + + template + using as_set_error = ::beman::execution::completion_signatures<::beman::execution::set_error_t(E)...>; + + template + using is_not_set_value = ::std::negation<::beman::execution::detail::is_set_value>; + template struct get_signatures; template @@ -121,18 +133,21 @@ struct continues_on_t { struct get_signatures< ::beman::execution::detail::basic_sender<::beman::execution::detail::continues_on_t, Scheduler, Sender>, Env> { - using scheduler_sender = ::beman::execution::schedule_result_t; - using additional_signatures = ::std::conditional_t< - ::beman::execution::sends_stopped, - ::beman::execution::completion_signatures<::beman::execution::set_error_t(::std::exception_ptr), - ::beman::execution::set_stopped_t()>, + using exception_signature = ::std::conditional_t< + ::std::is_nothrow_move_constructible_v>, + ::beman::execution::completion_signatures<>, ::beman::execution::completion_signatures<::beman::execution::set_error_t(::std::exception_ptr)>>; - template - using as_set_error = ::beman::execution::completion_signatures<::beman::execution::set_error_t(E)...>; - using type = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::combine< - decltype(::beman::execution::get_completion_signatures()), - ::beman::execution::error_types_of_t, - additional_signatures>>; + + static consteval auto get() { + [[maybe_unused]] auto child_sigs = ::beman::execution::get_completion_signatures(); + [[maybe_unused]] auto sched_sigs = + ::beman::execution::get_completion_signatures<::beman::execution::schedule_result_t, Env>(); + using child_sigs_t = decltype(child_sigs); + using extra_sigs_t = ::beman::execution::detail::meta::filter; + using type = ::beman::execution::detail::meta::unique< + ::beman::execution::detail::meta::combine>; + return type{}; + } }; template @@ -170,8 +185,8 @@ struct continues_on_t { public: template - static consteval auto get_completion_signatures() noexcept { - return typename get_signatures<::std::remove_cvref_t, Env...>::type{}; + static consteval auto get_completion_signatures() { + return get_signatures<::std::remove_cvref_t, Env...>::get(); } struct impls_for : ::beman::execution::detail::default_impls { @@ -190,7 +205,7 @@ struct continues_on_t { State* state; auto set_value() && noexcept -> void { - constexpr bool nothrow = std::is_nothrow_move_constructible_vasync_result)>; + constexpr bool nothrow = ::std::is_nothrow_move_constructible_vasync_result)>; try { ::std::visit( [this](Tuple& result) noexcept -> void { @@ -252,14 +267,8 @@ struct continues_on_t { auto sch{sender.template get<1>()}; using sched_t = ::std::remove_cvref_t; - using variant_t = ::beman::execution::detail::meta::unique<::beman::execution::detail::meta::prepend< - ::std::monostate, - ::beman::execution::detail::meta::transform< - ::beman::execution::detail::as_tuple_t, - ::beman::execution::detail::meta::to<::std::variant, - ::beman::execution::completion_signatures_of_t< - ::beman::execution::detail::child_type, - ::beman::execution::env_of_t>>>>>; + using variant_t = variant_type<::beman::execution::detail::child_type, + ::beman::execution::env_of_t>; return state_type(sch, receiver); }; @@ -270,7 +279,7 @@ struct continues_on_t { template auto operator()(auto, auto& state, auto& receiver, Tag, Args&&... args) const noexcept -> void { using result_t = ::beman::execution::detail::decayed_tuple; - constexpr bool nothrow = ::std::is_nothrow_constructible_v; + constexpr bool nothrow = ::std::is_nothrow_move_constructible_v; try { [&]() noexcept(nothrow) { diff --git a/include/beman/execution/detail/let.hpp b/include/beman/execution/detail/let.hpp index 97f8a14b..a83d5efc 100644 --- a/include/beman/execution/detail/let.hpp +++ b/include/beman/execution/detail/let.hpp @@ -170,48 +170,52 @@ struct let_t { using let_env_t = decltype(let_env(::std::declval(), ::std::declval())); private: + template + struct apply_decayed; + template + struct apply_decayed { + static_assert(::std::invocable&...>, + "The callback function object of the `let` adapter shall be invocable with `Args&...`"); + using sender_type = ::beman::execution::detail::call_result_t&...>; + static_assert(::beman::execution::sender, "`Fun` shall return a sender"); + using completions = ::std::conditional_t< + noexcept(::std::declval()(::std::declval<::std::decay_t&>()...)), + ::beman::execution::completion_signatures<>, + ::beman::execution::completion_signatures<::beman::execution::set_error_t(::std::exception_ptr)>>; + }; + template struct get_signatures; - template + template requires ::beman::execution::detail::non_dependent_successor::value struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>> - : get_signatures<::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>, - ::beman::execution::env<>> {}; + ::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>> + : get_signatures< + ::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>, + ::beman::execution::env<>> {}; - template + template struct get_signatures< - ::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>, + ::beman::execution::detail::basic_sender<::beman::execution::detail::let_t, Fun, Child>, Env> { template - using other_completion = let_other_completion; + using other_completion = let_other_completion; template - using matching_completion = let_matching_completion; - - template - struct apply_decayed; - template - struct apply_decayed { - using sender_type = ::beman::execution::detail::call_result_t...>; - using completions = ::std::conditional_t< - noexcept(::std::declval()(::std::declval<::std::decay_t>()...)), - ::beman::execution::completion_signatures<>, - ::beman::execution::completion_signatures<::beman::execution::set_error_t(::std::exception_ptr)>>; - }; + using matching_completion = let_matching_completion; using successor_env = ::beman::execution::detail::join_env, ::beman::execution::detail::fwd_env>; template struct get_completions; - template