2222#include " __concepts.hpp"
2323#include " __connect.hpp"
2424#include " __meta.hpp"
25+ #include " __queries.hpp"
2526#include " __tag_invoke.hpp"
2627#include " __type_traits.hpp"
2728
2829#include < exception>
30+ #include < functional> // for std::identity
2931#include < system_error>
3032#include < variant>
3133
@@ -49,6 +51,23 @@ namespace STDEXEC
4951 template <class _Sender , class _Promise >
5052 using __value_t = __decay_t <
5153 __value_types_of_t <_Sender, env_of_t <_Promise&>, __q<__single_value>, __msingle_or<void >>>;
54+
55+ inline constexpr auto __get_await_completion_adaptor =
56+ __with_default{get_await_completion_adaptor, std::identity{}};
57+
58+ template <class _Sender >
59+ using __adapt_completion_t = __result_of<__get_await_completion_adaptor, env_of_t <_Sender>>;
60+
61+ template <class _Sender >
62+ constexpr auto __adapt_sender_for_await (_Sender&& __sndr)
63+ noexcept (__nothrow_callable<__adapt_completion_t <_Sender>, _Sender>) -> decltype(auto )
64+ {
65+ return __get_await_completion_adaptor (get_env (__sndr))(static_cast <_Sender&&>(__sndr));
66+ }
67+
68+ template <class _Sender >
69+ using __adapted_sender_t =
70+ __remove_rvalue_reference_t <__call_result_t <__adapt_completion_t <_Sender>, _Sender>>;
5271 } // namespace __detail
5372
5473 // ///////////////////////////////////////////////////////////////////////////
@@ -185,14 +204,23 @@ namespace STDEXEC
185204 };
186205
187206 template <class _Sender , class _Promise >
188- concept __awaitable_sender = sender_in<_Sender, env_of_t <_Promise&>>
189- && __minvocable_q<__detail::__value_t , _Sender, _Promise>
190- && sender_to<_Sender, __receiver_t <_Sender, _Promise>>
191- && requires (_Promise& __promise) {
192- {
193- __promise.unhandled_stopped ()
194- } -> __std::convertible_to<__std::coroutine_handle<>>;
195- };
207+ STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE
208+ __sender_awaitable (_Sender&&, __std::coroutine_handle<_Promise>)
209+ -> __sender_awaitable<_Promise, _Sender>;
210+
211+ template <class _Sender , class _Promise >
212+ concept __awaitable_adapted_sender = sender_in<_Sender, env_of_t <_Promise&>>
213+ && __minvocable_q<__detail::__value_t , _Sender, _Promise>
214+ && sender_to<_Sender, __receiver_t <_Sender, _Promise>>
215+ && requires (_Promise& __promise) {
216+ {
217+ __promise.unhandled_stopped ()
218+ } -> __std::convertible_to<__std::coroutine_handle<>>;
219+ };
220+
221+ template <class _Sender , class _Promise >
222+ concept __awaitable_sender =
223+ __awaitable_adapted_sender<__detail::__adapted_sender_t <_Sender>, _Promise>;
196224
197225 struct __unspecified
198226 {
@@ -214,32 +242,33 @@ namespace STDEXEC
214242 template <class _Tp , class _Promise >
215243 static consteval auto __get_declfn () noexcept
216244 {
217- using __as_awaitable::__unspecified ;
245+ using namespace __as_awaitable ;
218246 if constexpr (__connect_await::__has_as_awaitable_member<_Tp, _Promise>)
219247 {
220248 using __result_t = decltype (__declval<_Tp>().as_awaitable (__declval<_Promise&>()));
221249 constexpr bool __is_nothrow = noexcept (
222250 __declval<_Tp>().as_awaitable (__declval<_Promise&>()));
223251 return __declfn<__result_t , __is_nothrow>();
224- // NOLINTNEXTLINE(bugprone-branch-clone)
225252 }
226- else if constexpr (__awaitable<_Tp, __unspecified>)
227- { // NOT __awaitable<_Tp, _Promise> !!
253+ else if constexpr (__awaitable<_Tp, __unspecified>) // NOT __awaitable<_Tp, _Promise> !!
254+ { // NOLINT(bugprone-branch-clone)
228255 return __declfn<_Tp&&>();
229256 }
230- else if constexpr (__as_awaitable:: __awaitable_sender<_Tp, _Promise>)
257+ else if constexpr (__awaitable_sender<_Tp, _Promise>)
231258 {
232- using __result_t = __as_awaitable::__sender_awaitable<_Promise, _Tp>;
233- constexpr bool __is_nothrow =
234- __nothrow_constructible_from<__result_t , _Tp, __std::coroutine_handle<_Promise>>;
259+ using __result_t = decltype ( //
260+ __sender_awaitable{__detail::__adapt_sender_for_await (__declval<_Tp>()),
261+ __std::coroutine_handle<_Promise>()});
262+ constexpr bool __is_nothrow = noexcept (
263+ __sender_awaitable{__detail::__adapt_sender_for_await (__declval<_Tp>()),
264+ __std::coroutine_handle<_Promise>()});
235265 return __declfn<__result_t , __is_nothrow>();
236- // NOT TO SPEC
237266 }
238- else if constexpr (__as_awaitable:: __incompatible_sender<_Tp, _Promise>)
267+ else if constexpr (__incompatible_sender<_Tp, _Promise>)
239268 {
240- // It's a sender, but it isn't a sender in the current promise's environment, so
241- // we can return the error type that results from trying to compute the sender's
242- // value type:
269+ // NOT TO SPEC: It's a sender, but it isn't a sender in the current promise's
270+ // environment, so we can return the error type that results from trying to
271+ // compute the sender's value type:
243272 return __declfn<__detail::__value_t <_Tp, _Promise>>();
244273 }
245274 else
@@ -253,24 +282,24 @@ namespace STDEXEC
253282 auto operator ()(_Tp&& __t , _Promise& __promise) const noexcept (noexcept (_DeclFn()))
254283 -> decltype(_DeclFn())
255284 {
256- using __as_awaitable::__unspecified ;
285+ using namespace __as_awaitable ;
257286 if constexpr (__connect_await::__has_as_awaitable_member<_Tp, _Promise>)
258287 {
259288 using __result_t = decltype (static_cast <_Tp&&>(__t ).as_awaitable (__promise));
260289 static_assert (__awaitable<__result_t , _Promise>);
261290 return static_cast <_Tp&&>(__t ).as_awaitable (__promise);
262- // NOLINTNEXTLINE(bugprone-branch-clone)
263291 }
264- else if constexpr (__awaitable<_Tp, __unspecified>)
265- { // NOT __awaitable<_Tp, _Promise> !!
292+ else if constexpr (__awaitable<_Tp, __unspecified>) // NOT __awaitable<_Tp, _Promise> !!
293+ { // NOLINT(bugprone-branch-clone)
266294 return static_cast <_Tp&&>(__t );
267295 }
268- else if constexpr (__as_awaitable:: __awaitable_sender<_Tp, _Promise>)
296+ else if constexpr (__awaitable_sender<_Tp, _Promise>)
269297 {
270298 auto __hcoro = __std::coroutine_handle<_Promise>::from_promise (__promise);
271- return __as_awaitable::__sender_awaitable<_Promise, _Tp>{static_cast <_Tp&&>(__t ), __hcoro};
299+ return __sender_awaitable{__detail::__adapt_sender_for_await (static_cast <_Tp&&>(__t )),
300+ __hcoro};
272301 }
273- else if constexpr (__as_awaitable:: __incompatible_sender<_Tp, _Promise>)
302+ else if constexpr (__incompatible_sender<_Tp, _Promise>)
274303 {
275304 return __detail::__value_t <_Tp, _Promise>();
276305 }
0 commit comments