@@ -79,7 +79,7 @@ namespace stdexec {
7979 };
8080
8181 template <class _Sender >
82- constexpr bool __is_nothrow_transform_sender () {
82+ constexpr bool __is_nothrow_transform_sender () noexcept {
8383 if constexpr (__callable<__sexpr_apply_t , _Sender, __domain::__legacy_customization>) {
8484 return __nothrow_callable<__sexpr_apply_t , _Sender, __domain::__legacy_customization>;
8585 } else if constexpr (__domain::__has_default_transform_sender<_Sender>) {
@@ -101,6 +101,43 @@ namespace stdexec {
101101 }
102102 } // namespace __domain
103103
104+ namespace __detail {
105+ // /////////////////////////////////////////////////////////////////////////
106+ template <class _Env , class _Tag >
107+ using __completion_scheduler_for =
108+ __meval_or<__call_result_t , __none_such, get_completion_scheduler_t <_Tag>, _Env>;
109+
110+ template <class _Env , class _Tag >
111+ using __completion_domain_for =
112+ __meval_or<__call_result_t , __none_such, get_domain_t , __completion_scheduler_for<_Env, _Tag>>;
113+
114+ // Check the value, error, and stopped channels for completion schedulers.
115+ // Of the completion schedulers that are known, they must all have compatible
116+ // domains. This computes that domain, or else returns __none_such if there
117+ // are no completion schedulers or if they don't specify a domain.
118+ template <class _Env >
119+ struct __completion_domain_or_none_
120+ : __mdefer_<
121+ __mtransform<
122+ __mbind_front_q<__completion_domain_for, _Env>,
123+ __mremove<__none_such, __munique<__msingle_or<__none_such>>>>,
124+ set_value_t ,
125+ set_error_t ,
126+ set_stopped_t > { };
127+
128+ template <class _Sender >
129+ using __completion_domain_or_none = __t <__completion_domain_or_none_<env_of_t <_Sender>>>;
130+
131+ template <class _Sender >
132+ concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>;
133+
134+ template <class _Sender >
135+ concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>);
136+
137+ template <__has_completion_domain _Sender>
138+ using __completion_domain_of = __completion_domain_or_none<_Sender>;
139+ } // namespace __detail
140+
104141 struct default_domain {
105142 default_domain () = default ;
106143
@@ -160,43 +197,6 @@ namespace stdexec {
160197 }
161198 };
162199
163- // ///////////////////////////////////////////////////////////////////////////
164- namespace __detail {
165- template <class _Env , class _Tag >
166- using __completion_scheduler_for =
167- __meval_or<__call_result_t , __none_such, get_completion_scheduler_t <_Tag>, _Env>;
168-
169- template <class _Env , class _Tag >
170- using __completion_domain_for =
171- __meval_or<__call_result_t , __none_such, get_domain_t , __completion_scheduler_for<_Env, _Tag>>;
172-
173- // Check the value, error, and stopped channels for completion schedulers.
174- // Of the completion schedulers that are known, they must all have compatible
175- // domains. This computes that domain, or else returns __none_such if there
176- // are no completion schedulers or if they don't specify a domain.
177- template <class _Env >
178- struct __completion_domain_or_none_
179- : __mdefer_<
180- __mtransform<
181- __mbind_front_q<__completion_domain_for, _Env>,
182- __mremove<__none_such, __munique<__msingle_or<__none_such>>>>,
183- set_value_t ,
184- set_error_t ,
185- set_stopped_t > { };
186-
187- template <class _Sender >
188- using __completion_domain_or_none = __t <__completion_domain_or_none_<env_of_t <_Sender>>>;
189-
190- template <class _Sender >
191- concept __consistent_completion_domains = __mvalid<__completion_domain_or_none, _Sender>;
192-
193- template <class _Sender >
194- concept __has_completion_domain = (!same_as<__completion_domain_or_none<_Sender>, __none_such>);
195-
196- template <__has_completion_domain _Sender>
197- using __completion_domain_of = __completion_domain_or_none<_Sender>;
198- } // namespace __detail
199-
200200 // ///////////////////////////////////////////////////////////////////////////
201201 // ! Function object implementing `get-domain-early(snd)`
202202 // ! from [exec.snd.general] item 3.9. It is the first well-formed expression of
@@ -253,11 +253,29 @@ namespace stdexec {
253253 template <class _Sender , class _Env >
254254 using __late_domain_of_t = __call_result_t <__get_late_domain_t , _Sender, _Env>;
255255
256+ // ///////////////////////////////////////////////////////////////////////////
257+ // dependent_domain
258+ struct dependent_domain {
259+ // defined in __transform_sender.hpp
260+ template <class _Sender , class _Env >
261+ static constexpr auto __is_nothrow_transform_sender () noexcept -> bool;
262+
263+ // defined in __transform_sender.hpp
264+ template <sender_expr _Sender, class _Env >
265+ requires same_as<__early_domain_of_t <_Sender>, dependent_domain>
266+ STDEXEC_ATTRIBUTE ((always_inline))
267+ decltype (auto )
268+ transform_sender (_Sender&& __sndr, const _Env& __env) const
269+ noexcept (__is_nothrow_transform_sender<_Sender, _Env>());
270+ };
271+
256272 namespace __domain {
257273 struct __common_domain_fn {
258274 template <class ... _Domains>
259275 static auto __common_domain (_Domains...) noexcept {
260- if constexpr (__one_of<dependent_domain, _Domains...>) {
276+ if constexpr (sizeof ...(_Domains) == 0 ) {
277+ return default_domain ();
278+ } else if constexpr (__one_of<dependent_domain, _Domains...>) {
261279 return dependent_domain ();
262280 } else if constexpr (stdexec::__mvalid<std::common_type_t , _Domains...>) {
263281 return std::common_type_t <_Domains...>();
0 commit comments