From 21db1dfdd2326c971484c82592554a1404258436 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 16 Dec 2024 18:05:06 -0800 Subject: [PATCH 1/2] change the common domain computation to use `std::common_type` --- include/exec/static_thread_pool.hpp | 2 +- include/stdexec/__detail/__domain.hpp | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/exec/static_thread_pool.hpp b/include/exec/static_thread_pool.hpp index e03171004..97636b1bb 100644 --- a/include/exec/static_thread_pool.hpp +++ b/include/exec/static_thread_pool.hpp @@ -261,7 +261,7 @@ namespace exec { } public: - struct domain { + struct domain : stdexec::default_domain { // For eager customization template Sender> auto transform_sender(Sender&& sndr) const noexcept { diff --git a/include/stdexec/__detail/__domain.hpp b/include/stdexec/__detail/__domain.hpp index 1448a5d2d..b4727abfd 100644 --- a/include/stdexec/__detail/__domain.hpp +++ b/include/stdexec/__detail/__domain.hpp @@ -24,6 +24,7 @@ #include "__meta.hpp" #include "../functional.hpp" +#include "__utility.hpp" namespace stdexec { @@ -254,20 +255,15 @@ namespace stdexec { namespace __domain { struct __common_domain_fn { - static auto __common_domain() noexcept -> default_domain { - return {}; - } - - template - requires __all_of<_Domain, _OtherDomains...> - static auto __common_domain(_Domain __domain, _OtherDomains...) noexcept -> _Domain { - return static_cast<_Domain&&>(__domain); - } - template - static auto __common_domain(_Domains...) noexcept // - -> __if_c<__one_of, dependent_domain, __none_such> { - return {}; + static auto __common_domain(_Domains...) noexcept { + if constexpr (__one_of) { + return dependent_domain(); + } else if constexpr (stdexec::__mvalid) { + return std::common_type_t<_Domains...>(); + } else { + return __none_such(); + } } auto operator()(__ignore, __ignore, const auto&... __sndrs) const noexcept { From a92deeeb0c15b797ece2c83db64900f8d3fec504 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 18 Dec 2024 09:17:36 -0800 Subject: [PATCH 2/2] move dfn of `dependent_domain` into `__domain.hpp` --- include/stdexec/__detail/__domain.hpp | 96 +++++++++++-------- .../stdexec/__detail/__transform_sender.hpp | 14 --- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/include/stdexec/__detail/__domain.hpp b/include/stdexec/__detail/__domain.hpp index b4727abfd..f4ef2b8dd 100644 --- a/include/stdexec/__detail/__domain.hpp +++ b/include/stdexec/__detail/__domain.hpp @@ -79,7 +79,7 @@ namespace stdexec { }; template - constexpr bool __is_nothrow_transform_sender() { + constexpr bool __is_nothrow_transform_sender() noexcept { if constexpr (__callable<__sexpr_apply_t, _Sender, __domain::__legacy_customization>) { return __nothrow_callable<__sexpr_apply_t, _Sender, __domain::__legacy_customization>; } else if constexpr (__domain::__has_default_transform_sender<_Sender>) { @@ -101,6 +101,43 @@ namespace stdexec { } } // namespace __domain + namespace __detail { + /////////////////////////////////////////////////////////////////////////// + template + using __completion_scheduler_for = + __meval_or<__call_result_t, __none_such, get_completion_scheduler_t<_Tag>, _Env>; + + template + using __completion_domain_for = + __meval_or<__call_result_t, __none_such, get_domain_t, __completion_scheduler_for<_Env, _Tag>>; + + // Check the value, error, and stopped channels for completion schedulers. + // Of the completion schedulers that are known, they must all have compatible + // domains. This computes that domain, or else returns __none_such if there + // are no completion schedulers or if they don't specify a domain. + template + struct __completion_domain_or_none_ + : __mdefer_< + __mtransform< + __mbind_front_q<__completion_domain_for, _Env>, + __mremove<__none_such, __munique<__msingle_or<__none_such>>>>, + set_value_t, + set_error_t, + set_stopped_t> { }; + + template + using __completion_domain_or_none = __t<__completion_domain_or_none_>>; + + template + concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>; + + template + concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>); + + template <__has_completion_domain _Sender> + using __completion_domain_of = __completion_domain_or_none<_Sender>; + } // namespace __detail + struct default_domain { default_domain() = default; @@ -160,43 +197,6 @@ namespace stdexec { } }; - ///////////////////////////////////////////////////////////////////////////// - namespace __detail { - template - using __completion_scheduler_for = - __meval_or<__call_result_t, __none_such, get_completion_scheduler_t<_Tag>, _Env>; - - template - using __completion_domain_for = - __meval_or<__call_result_t, __none_such, get_domain_t, __completion_scheduler_for<_Env, _Tag>>; - - // Check the value, error, and stopped channels for completion schedulers. - // Of the completion schedulers that are known, they must all have compatible - // domains. This computes that domain, or else returns __none_such if there - // are no completion schedulers or if they don't specify a domain. - template - struct __completion_domain_or_none_ - : __mdefer_< - __mtransform< - __mbind_front_q<__completion_domain_for, _Env>, - __mremove<__none_such, __munique<__msingle_or<__none_such>>>>, - set_value_t, - set_error_t, - set_stopped_t> { }; - - template - using __completion_domain_or_none = __t<__completion_domain_or_none_>>; - - template - concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>; - - template - concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>); - - template <__has_completion_domain _Sender> - using __completion_domain_of = __completion_domain_or_none<_Sender>; - } // namespace __detail - ///////////////////////////////////////////////////////////////////////////// //! Function object implementing `get-domain-early(snd)` //! from [exec.snd.general] item 3.9. It is the first well-formed expression of @@ -253,11 +253,29 @@ namespace stdexec { template using __late_domain_of_t = __call_result_t<__get_late_domain_t, _Sender, _Env>; + ///////////////////////////////////////////////////////////////////////////// + // dependent_domain + struct dependent_domain { + // defined in __transform_sender.hpp + template + static constexpr auto __is_nothrow_transform_sender() noexcept -> bool; + + // defined in __transform_sender.hpp + template + requires same_as<__early_domain_of_t<_Sender>, dependent_domain> + STDEXEC_ATTRIBUTE((always_inline)) + decltype(auto) + transform_sender(_Sender&& __sndr, const _Env& __env) const + noexcept(__is_nothrow_transform_sender<_Sender, _Env>()); + }; + namespace __domain { struct __common_domain_fn { template static auto __common_domain(_Domains...) noexcept { - if constexpr (__one_of) { + if constexpr (sizeof...(_Domains) == 0) { + return default_domain(); + } else if constexpr (__one_of) { return dependent_domain(); } else if constexpr (stdexec::__mvalid) { return std::common_type_t<_Domains...>(); diff --git a/include/stdexec/__detail/__transform_sender.hpp b/include/stdexec/__detail/__transform_sender.hpp index 4a435336e..f398cfe30 100644 --- a/include/stdexec/__detail/__transform_sender.hpp +++ b/include/stdexec/__detail/__transform_sender.hpp @@ -31,20 +31,6 @@ STDEXEC_PRAGMA_PUSH() STDEXEC_PRAGMA_IGNORE_EDG(type_qualifiers_ignored_on_reference) namespace stdexec { - ///////////////////////////////////////////////////////////////////////////// - // dependent_domain - struct dependent_domain { - template - static constexpr auto __is_nothrow_transform_sender() noexcept -> bool; - - template - requires same_as<__early_domain_of_t<_Sender>, dependent_domain> - STDEXEC_ATTRIBUTE((always_inline)) - decltype(auto) - transform_sender(_Sender&& __sndr, const _Env& __env) const - noexcept(__is_nothrow_transform_sender<_Sender, _Env>()); - }; - ///////////////////////////////////////////////////////////////////////////// // [execution.transform_sender] namespace __domain {