15cee9157SPatrick Williams /* 25cee9157SPatrick Williams * Copyright (c) 2021-2024 NVIDIA Corporation 35cee9157SPatrick Williams * 45cee9157SPatrick Williams * Licensed under the Apache License Version 2.0 with LLVM Exceptions 55cee9157SPatrick Williams * (the "License"); you may not use this file except in compliance with 65cee9157SPatrick Williams * the License. You may obtain a copy of the License at 75cee9157SPatrick Williams * 85cee9157SPatrick Williams * https://llvm.org/LICENSE.txt 95cee9157SPatrick Williams * 105cee9157SPatrick Williams * Unless required by applicable law or agreed to in writing, software 115cee9157SPatrick Williams * distributed under the License is distributed on an "AS IS" BASIS, 125cee9157SPatrick Williams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135cee9157SPatrick Williams * See the License for the specific language governing permissions and 145cee9157SPatrick Williams * limitations under the License. 155cee9157SPatrick Williams */ 165cee9157SPatrick Williams #pragma once 175cee9157SPatrick Williams 185cee9157SPatrick Williams #include "__execution_fwd.hpp" 195cee9157SPatrick Williams 205cee9157SPatrick Williams // include these after __execution_fwd.hpp 215cee9157SPatrick Williams #include "__awaitable.hpp" 225cee9157SPatrick Williams #include "__completion_signatures.hpp" 235cee9157SPatrick Williams #include "__concepts.hpp" 245cee9157SPatrick Williams #include "__connect_awaitable.hpp" 255cee9157SPatrick Williams #include "__debug.hpp" 265cee9157SPatrick Williams #include "__env.hpp" 275cee9157SPatrick Williams #include "__operation_states.hpp" 285cee9157SPatrick Williams #include "__receivers.hpp" 295cee9157SPatrick Williams #include "__senders_core.hpp" 305cee9157SPatrick Williams #include "__transform_completion_signatures.hpp" 315cee9157SPatrick Williams #include "__transform_sender.hpp" 325cee9157SPatrick Williams #include "__type_traits.hpp" 335cee9157SPatrick Williams 345cee9157SPatrick Williams namespace stdexec 355cee9157SPatrick Williams { 365cee9157SPatrick Williams ///////////////////////////////////////////////////////////////////////////// 375cee9157SPatrick Williams // [execution.get_completion_signatures] 385cee9157SPatrick Williams namespace __detail 395cee9157SPatrick Williams { 405cee9157SPatrick Williams struct __dependent_completions 415cee9157SPatrick Williams {}; 425cee9157SPatrick Williams 435cee9157SPatrick Williams template <class _Completions> 445cee9157SPatrick Williams concept __well_formed_sender = 455cee9157SPatrick Williams __valid_completion_signatures<_Completions> || 465cee9157SPatrick Williams __same_as<_Completions, _ERROR_<__dependent_completions>>; 475cee9157SPatrick Williams } // namespace __detail 485cee9157SPatrick Williams 495cee9157SPatrick Williams using dependent_completions = _ERROR_<__detail::__dependent_completions>; 505cee9157SPatrick Williams 515cee9157SPatrick Williams namespace __sigs 525cee9157SPatrick Williams { 535cee9157SPatrick Williams template <class _Sender, class _Env> 545cee9157SPatrick Williams using __tfx_sender = 555cee9157SPatrick Williams transform_sender_result_t<__late_domain_of_t<_Sender, _Env>, _Sender, _Env>; 565cee9157SPatrick Williams 575cee9157SPatrick Williams template <class _Sender, class... _Env> 585cee9157SPatrick Williams using __member_result_t = 595cee9157SPatrick Williams decltype(__declval<_Sender>().get_completion_signatures( 605cee9157SPatrick Williams __declval<_Env>()...)); 615cee9157SPatrick Williams 625cee9157SPatrick Williams template <class _Sender, class... _Env> 635cee9157SPatrick Williams using __static_member_result_t = // 645cee9157SPatrick Williams decltype(STDEXEC_REMOVE_REFERENCE(_Sender) // 655cee9157SPatrick Williams ::get_completion_signatures(__declval<_Sender>(), 665cee9157SPatrick Williams __declval<_Env>()...)); 675cee9157SPatrick Williams 685cee9157SPatrick Williams template <class _Sender, class... _Env> 695cee9157SPatrick Williams concept __with_member = __mvalid<__member_result_t, _Sender, _Env...>; 705cee9157SPatrick Williams 715cee9157SPatrick Williams template <class _Sender, class... _Env> 725cee9157SPatrick Williams concept __with_static_member = 735cee9157SPatrick Williams __mvalid<__static_member_result_t, _Sender, _Env...>; 745cee9157SPatrick Williams 755cee9157SPatrick Williams template <class _Sender, class... _Env> 765cee9157SPatrick Williams concept __with_tag_invoke = // 775cee9157SPatrick Williams tag_invocable<get_completion_signatures_t, _Sender, _Env...>; 785cee9157SPatrick Williams 795cee9157SPatrick Williams template <class _Sender, class... _Env> 805cee9157SPatrick Williams concept __with_legacy_tag_invoke = // 815cee9157SPatrick Williams (sizeof...(_Env) == 0) && 825cee9157SPatrick Williams tag_invocable<get_completion_signatures_t, _Sender, empty_env>; 835cee9157SPatrick Williams 845cee9157SPatrick Williams template <class _Sender> 855cee9157SPatrick Williams using __member_alias_t = // 865cee9157SPatrick Williams typename __decay_t<_Sender>::completion_signatures; 875cee9157SPatrick Williams 885cee9157SPatrick Williams template <class _Sender> 895cee9157SPatrick Williams concept __with_member_alias = __mvalid<__member_alias_t, _Sender>; 905cee9157SPatrick Williams 915cee9157SPatrick Williams struct get_completion_signatures_t 925cee9157SPatrick Williams { 935cee9157SPatrick Williams template <class _Sender, class... _Env> __implstdexec::__sigs::get_completion_signatures_t945cee9157SPatrick Williams static auto __impl() 955cee9157SPatrick Williams { 965cee9157SPatrick Williams // Compute the type of the transformed sender: 975cee9157SPatrick Williams using __tfx_fn = 985cee9157SPatrick Williams __if_c<sizeof...(_Env) == 0, __mconst<_Sender>, __q<__tfx_sender>>; 995cee9157SPatrick Williams using _TfxSender = __minvoke<__tfx_fn, _Sender, _Env...>; 1005cee9157SPatrick Williams 1015cee9157SPatrick Williams if constexpr (__merror<_TfxSender>) 1025cee9157SPatrick Williams { 1035cee9157SPatrick Williams // Computing the type of the transformed sender returned an error 1045cee9157SPatrick Williams // type. Propagate it. 1055cee9157SPatrick Williams return static_cast<_TfxSender (*)()>(nullptr); 1065cee9157SPatrick Williams } 1075cee9157SPatrick Williams else if constexpr (__with_member_alias<_TfxSender>) 1085cee9157SPatrick Williams { 1095cee9157SPatrick Williams using _Result = __member_alias_t<_TfxSender>; 1105cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1115cee9157SPatrick Williams } 1125cee9157SPatrick Williams else if constexpr (__with_static_member<_TfxSender, _Env...>) 1135cee9157SPatrick Williams { 1145cee9157SPatrick Williams using _Result = __static_member_result_t<_TfxSender, _Env...>; 1155cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1165cee9157SPatrick Williams } 1175cee9157SPatrick Williams else if constexpr (__with_member<_TfxSender, _Env...>) 1185cee9157SPatrick Williams { 1195cee9157SPatrick Williams using _Result = __member_result_t<_TfxSender, _Env...>; 1205cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1215cee9157SPatrick Williams } 1225cee9157SPatrick Williams else if constexpr (__with_tag_invoke<_TfxSender, _Env...>) 1235cee9157SPatrick Williams { 1245cee9157SPatrick Williams using _Result = tag_invoke_result_t<get_completion_signatures_t, 1255cee9157SPatrick Williams _TfxSender, _Env...>; 1265cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1275cee9157SPatrick Williams } 1285cee9157SPatrick Williams else if constexpr (__with_legacy_tag_invoke<_TfxSender, _Env...>) 1295cee9157SPatrick Williams { 1305cee9157SPatrick Williams // This branch is strictly for backwards compatibility 1315cee9157SPatrick Williams using _Result = tag_invoke_result_t<get_completion_signatures_t, 1325cee9157SPatrick Williams _Sender, empty_env>; 1335cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1345cee9157SPatrick Williams // [WAR] The explicit cast to bool below is to work around a bug in 1355cee9157SPatrick Williams // nvc++ (nvbug#4707793) 1365cee9157SPatrick Williams } 1375cee9157SPatrick Williams else if constexpr (bool(__awaitable<_TfxSender, 1385cee9157SPatrick Williams __env::__promise<_Env>...>)) 1395cee9157SPatrick Williams { 1405cee9157SPatrick Williams using _AwaitResult = 1415cee9157SPatrick Williams __await_result_t<_TfxSender, __env::__promise<_Env>...>; 1425cee9157SPatrick Williams using _Result = completion_signatures< 1435cee9157SPatrick Williams // set_value_t() or set_value_t(T) 1445cee9157SPatrick Williams __minvoke<__mremove<void, __qf<set_value_t>>, _AwaitResult>, 1455cee9157SPatrick Williams set_error_t(std::exception_ptr), set_stopped_t()>; 1465cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1475cee9157SPatrick Williams } 1485cee9157SPatrick Williams else if constexpr (sizeof...(_Env) == 0) 1495cee9157SPatrick Williams { 1505cee9157SPatrick Williams // It's possible this is a dependent sender. 1515cee9157SPatrick Williams return static_cast<dependent_completions (*)()>(nullptr); 1525cee9157SPatrick Williams } 1535cee9157SPatrick Williams else if constexpr ((__is_debug_env<_Env> || ...)) 1545cee9157SPatrick Williams { 1555cee9157SPatrick Williams using __tag_invoke::tag_invoke; 1565cee9157SPatrick Williams // This ought to cause a hard error that indicates where the problem 1575cee9157SPatrick Williams // is. 1585cee9157SPatrick Williams using _Completions [[maybe_unused]] = 1595cee9157SPatrick Williams tag_invoke_result_t<get_completion_signatures_t, _Sender, 1605cee9157SPatrick Williams _Env...>; 1615cee9157SPatrick Williams return static_cast<__debug::__completion_signatures (*)()>(nullptr); 1625cee9157SPatrick Williams } 1635cee9157SPatrick Williams else 1645cee9157SPatrick Williams { 1655cee9157SPatrick Williams using _Result = __mexception<_UNRECOGNIZED_SENDER_TYPE_<>, 1665cee9157SPatrick Williams _WITH_SENDER_<_Sender>, 1675cee9157SPatrick Williams _WITH_ENVIRONMENT_<_Env>...>; 1685cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 1695cee9157SPatrick Williams } 1705cee9157SPatrick Williams } 1715cee9157SPatrick Williams 1725cee9157SPatrick Williams // NOT TO SPEC: if we're unable to compute the completion signatures, 1735cee9157SPatrick Williams // return an error type instead of SFINAE. 1745cee9157SPatrick Williams template <class _Sender, class... _Env> 1755cee9157SPatrick Williams requires(sizeof...(_Env) <= 1) operator ()stdexec::__sigs::get_completion_signatures_t1765cee9157SPatrick Williams constexpr auto operator()(_Sender&&, _Env&&...) const noexcept // 1775cee9157SPatrick Williams -> decltype(__impl<_Sender, _Env...>()()) 1785cee9157SPatrick Williams { 1795cee9157SPatrick Williams return {}; 1805cee9157SPatrick Williams } 1815cee9157SPatrick Williams }; 1825cee9157SPatrick Williams } // namespace __sigs 1835cee9157SPatrick Williams 1845cee9157SPatrick Williams using __sigs::get_completion_signatures_t; 1855cee9157SPatrick Williams inline constexpr get_completion_signatures_t get_completion_signatures{}; 1865cee9157SPatrick Williams 1875cee9157SPatrick Williams ///////////////////////////////////////////////////////////////////////////// 1885cee9157SPatrick Williams // [execution.senders.connect] 1895cee9157SPatrick Williams namespace __connect 1905cee9157SPatrick Williams { 1915cee9157SPatrick Williams template <class _Sender, class _Receiver> 1925cee9157SPatrick Williams using __tfx_sender = // 1935cee9157SPatrick Williams transform_sender_result_t<__late_domain_of_t<_Sender, env_of_t<_Receiver>>, 1945cee9157SPatrick Williams _Sender, env_of_t<_Receiver>>; 1955cee9157SPatrick Williams 1965cee9157SPatrick Williams template <class _Sender, class _Receiver> 1975cee9157SPatrick Williams using __member_result_t = 1985cee9157SPatrick Williams decltype(__declval<_Sender>().connect(__declval<_Receiver>())); 1995cee9157SPatrick Williams 2005cee9157SPatrick Williams template <class _Sender, class _Receiver> 2015cee9157SPatrick Williams using __static_member_result_t = 2025cee9157SPatrick Williams decltype(STDEXEC_REMOVE_REFERENCE(_Sender) // 2035cee9157SPatrick Williams ::connect(__declval<_Sender>(), __declval<_Receiver>())); 2045cee9157SPatrick Williams 2055cee9157SPatrick Williams template <class _Sender, class _Receiver> 2065cee9157SPatrick Williams concept __with_member = __mvalid<__member_result_t, _Sender, _Receiver>; 2075cee9157SPatrick Williams 2085cee9157SPatrick Williams template <class _Sender, class _Receiver> 2095cee9157SPatrick Williams concept __with_static_member = 2105cee9157SPatrick Williams __mvalid<__static_member_result_t, _Sender, _Receiver>; 2115cee9157SPatrick Williams 2125cee9157SPatrick Williams template <class _Sender, class _Receiver> 2135cee9157SPatrick Williams concept __with_tag_invoke = tag_invocable<connect_t, _Sender, _Receiver>; 2145cee9157SPatrick Williams 2155cee9157SPatrick Williams template <class _Sender, class _Receiver> 2165cee9157SPatrick Williams concept __with_co_await = __callable<__connect_awaitable_t, _Sender, _Receiver>; 2175cee9157SPatrick Williams 2185cee9157SPatrick Williams struct connect_t 2195cee9157SPatrick Williams { 2205cee9157SPatrick Williams template <class _Sender, class _Env> __check_signaturesstdexec::__connect::connect_t2215cee9157SPatrick Williams static constexpr auto __check_signatures() -> bool 2225cee9157SPatrick Williams { 2235cee9157SPatrick Williams if constexpr (sender_in<_Sender, _Env>) 2245cee9157SPatrick Williams { 2255cee9157SPatrick Williams // Instantiate __debug_sender via completion_signatures_of_t to 2265cee9157SPatrick Williams // check that the actual completions match the expected completions. 2275cee9157SPatrick Williams // 2285cee9157SPatrick Williams // Instantiate completion_signatures_of_t only if sender_in is true 2295cee9157SPatrick Williams // to workaround Clang not implementing CWG#2369 yet (connect() does 2305cee9157SPatrick Williams // not have a constraint for _Sender satisfying sender_in). 2315cee9157SPatrick Williams using __checked_signatures 2325cee9157SPatrick Williams [[maybe_unused]] = completion_signatures_of_t<_Sender, _Env>; 2335cee9157SPatrick Williams } 2345cee9157SPatrick Williams return true; 2355cee9157SPatrick Williams } 2365cee9157SPatrick Williams 2375cee9157SPatrick Williams template <class _Sender, class _Receiver> __select_implstdexec::__connect::connect_t2385cee9157SPatrick Williams static constexpr auto __select_impl() noexcept 2395cee9157SPatrick Williams { 2405cee9157SPatrick Williams using _Domain = __late_domain_of_t<_Sender, env_of_t<_Receiver>>; 2415cee9157SPatrick Williams using _TfxSender = __tfx_sender<_Sender, _Receiver>; 2425cee9157SPatrick Williams constexpr bool _NothrowTfxSender = 2435cee9157SPatrick Williams __nothrow_callable<transform_sender_t, _Domain, _Sender, 2445cee9157SPatrick Williams env_of_t<_Receiver>>; 2455cee9157SPatrick Williams 2465cee9157SPatrick Williams #if STDEXEC_ENABLE_EXTRA_TYPE_CHECKING() 2475cee9157SPatrick Williams static_assert(__check_signatures<_TfxSender, env_of_t<_Receiver>>()); 2485cee9157SPatrick Williams #endif 2495cee9157SPatrick Williams 2505cee9157SPatrick Williams if constexpr (__with_static_member<_TfxSender, _Receiver>) 2515cee9157SPatrick Williams { 2525cee9157SPatrick Williams using _Result = __static_member_result_t<_TfxSender, _Receiver>; 2535cee9157SPatrick Williams constexpr bool _Nothrow = // 254*06f265f6SPatrick Williams _NothrowTfxSender && 255*06f265f6SPatrick Williams noexcept(__declval<_TfxSender>().connect( 2565cee9157SPatrick Williams __declval<_TfxSender>(), __declval<_Receiver>())); 2575cee9157SPatrick Williams return static_cast<_Result (*)() noexcept(_Nothrow)>(nullptr); 2585cee9157SPatrick Williams } 2595cee9157SPatrick Williams else if constexpr (__with_member<_TfxSender, _Receiver>) 2605cee9157SPatrick Williams { 2615cee9157SPatrick Williams using _Result = __member_result_t<_TfxSender, _Receiver>; 2625cee9157SPatrick Williams constexpr bool _Nothrow = // 263*06f265f6SPatrick Williams _NothrowTfxSender && noexcept(__declval<_TfxSender>().connect( 264*06f265f6SPatrick Williams __declval<_Receiver>())); 2655cee9157SPatrick Williams return static_cast<_Result (*)() noexcept(_Nothrow)>(nullptr); 2665cee9157SPatrick Williams } 2675cee9157SPatrick Williams else if constexpr (__with_tag_invoke<_TfxSender, _Receiver>) 2685cee9157SPatrick Williams { 2695cee9157SPatrick Williams using _Result = 2705cee9157SPatrick Williams tag_invoke_result_t<connect_t, _TfxSender, _Receiver>; 2715cee9157SPatrick Williams constexpr bool _Nothrow = // 2725cee9157SPatrick Williams _NothrowTfxSender && 2735cee9157SPatrick Williams nothrow_tag_invocable<connect_t, _TfxSender, _Receiver>; 2745cee9157SPatrick Williams return static_cast<_Result (*)() noexcept(_Nothrow)>(nullptr); 2755cee9157SPatrick Williams } 2765cee9157SPatrick Williams else if constexpr (__with_co_await<_TfxSender, _Receiver>) 2775cee9157SPatrick Williams { 2785cee9157SPatrick Williams using _Result = 2795cee9157SPatrick Williams __call_result_t<__connect_awaitable_t, _TfxSender, _Receiver>; 2805cee9157SPatrick Williams return static_cast<_Result (*)()>(nullptr); 2815cee9157SPatrick Williams } 2825cee9157SPatrick Williams else 2835cee9157SPatrick Williams { 2845cee9157SPatrick Williams using _Result = __debug::__debug_operation; 2855cee9157SPatrick Williams return static_cast<_Result (*)() noexcept(_NothrowTfxSender)>( 2865cee9157SPatrick Williams nullptr); 2875cee9157SPatrick Williams } 2885cee9157SPatrick Williams } 2895cee9157SPatrick Williams 2905cee9157SPatrick Williams template <class _Sender, class _Receiver> 2915cee9157SPatrick Williams using __select_impl_t = decltype(__select_impl<_Sender, _Receiver>()); 2925cee9157SPatrick Williams 2935cee9157SPatrick Williams template <sender _Sender, receiver _Receiver> 2945cee9157SPatrick Williams requires __with_static_member<__tfx_sender<_Sender, _Receiver>, 2955cee9157SPatrick Williams _Receiver> || 296*06f265f6SPatrick Williams __with_member<__tfx_sender<_Sender, _Receiver>, 297*06f265f6SPatrick Williams _Receiver> || 2985cee9157SPatrick Williams __with_tag_invoke<__tfx_sender<_Sender, _Receiver>, 2995cee9157SPatrick Williams _Receiver> || 300*06f265f6SPatrick Williams __with_co_await<__tfx_sender<_Sender, _Receiver>, 301*06f265f6SPatrick Williams _Receiver> || 3025cee9157SPatrick Williams __is_debug_env<env_of_t<_Receiver>> 3035cee9157SPatrick Williams auto operator()(_Sender&& __sndr, _Receiver&& __rcvr) const 3045cee9157SPatrick Williams noexcept(__nothrow_callable<__select_impl_t<_Sender, _Receiver>>) 3055cee9157SPatrick Williams -> __call_result_t<__select_impl_t<_Sender, _Receiver>> 3065cee9157SPatrick Williams { 3075cee9157SPatrick Williams using _TfxSender = __tfx_sender<_Sender, _Receiver>; 3085cee9157SPatrick Williams auto&& __env = get_env(__rcvr); 3095cee9157SPatrick Williams auto __domain = __get_late_domain(__sndr, __env); 3105cee9157SPatrick Williams 3115cee9157SPatrick Williams if constexpr (__with_static_member<_TfxSender, _Receiver>) 3125cee9157SPatrick Williams { 3135cee9157SPatrick Williams static_assert( 3145cee9157SPatrick Williams operation_state< 3155cee9157SPatrick Williams __static_member_result_t<_TfxSender, _Receiver>>, 3165cee9157SPatrick Williams "Sender::connect(sender, receiver) must return a type that " 3175cee9157SPatrick Williams "satisfies the operation_state concept"); 3185cee9157SPatrick Williams auto&& __tfx_sndr = transform_sender( 3195cee9157SPatrick Williams __domain, static_cast<_Sender&&>(__sndr), __env); 3205cee9157SPatrick Williams return __tfx_sndr.connect(static_cast<_TfxSender&&>(__tfx_sndr), 3215cee9157SPatrick Williams static_cast<_Receiver&&>(__rcvr)); 3225cee9157SPatrick Williams } 3235cee9157SPatrick Williams else if constexpr (__with_member<_TfxSender, _Receiver>) 3245cee9157SPatrick Williams { 3255cee9157SPatrick Williams static_assert( 3265cee9157SPatrick Williams operation_state<__member_result_t<_TfxSender, _Receiver>>, 3275cee9157SPatrick Williams "sender.connect(receiver) must return a type that " 3285cee9157SPatrick Williams "satisfies the operation_state concept"); 3295cee9157SPatrick Williams return transform_sender(__domain, static_cast<_Sender&&>(__sndr), 3305cee9157SPatrick Williams __env) 3315cee9157SPatrick Williams .connect(static_cast<_Receiver&&>(__rcvr)); 3325cee9157SPatrick Williams } 3335cee9157SPatrick Williams else if constexpr (__with_tag_invoke<_TfxSender, _Receiver>) 3345cee9157SPatrick Williams { 3355cee9157SPatrick Williams static_assert( 3365cee9157SPatrick Williams operation_state< 3375cee9157SPatrick Williams tag_invoke_result_t<connect_t, _TfxSender, _Receiver>>, 3385cee9157SPatrick Williams "stdexec::connect(sender, receiver) must return a type that " 3395cee9157SPatrick Williams "satisfies the operation_state concept"); 340*06f265f6SPatrick Williams return tag_invoke( 341*06f265f6SPatrick Williams connect_t(), 342*06f265f6SPatrick Williams transform_sender(__domain, static_cast<_Sender&&>(__sndr), 3435cee9157SPatrick Williams __env), 3445cee9157SPatrick Williams static_cast<_Receiver&&>(__rcvr)); 3455cee9157SPatrick Williams } 3465cee9157SPatrick Williams else if constexpr (__with_co_await<_TfxSender, _Receiver>) 3475cee9157SPatrick Williams { 3485cee9157SPatrick Williams return __connect_awaitable( // 3495cee9157SPatrick Williams transform_sender(__domain, static_cast<_Sender&&>(__sndr), 3505cee9157SPatrick Williams __env), 3515cee9157SPatrick Williams static_cast<_Receiver&&>(__rcvr)); 3525cee9157SPatrick Williams } 3535cee9157SPatrick Williams else 3545cee9157SPatrick Williams { 3555cee9157SPatrick Williams // This should generate an instantiation backtrace that contains 3565cee9157SPatrick Williams // useful debugging information. 3575cee9157SPatrick Williams using __tag_invoke::tag_invoke; 3585cee9157SPatrick Williams tag_invoke(*this, 3595cee9157SPatrick Williams transform_sender(__domain, 3605cee9157SPatrick Williams static_cast<_Sender&&>(__sndr), __env), 3615cee9157SPatrick Williams static_cast<_Receiver&&>(__rcvr)); 3625cee9157SPatrick Williams } 3635cee9157SPatrick Williams } 3645cee9157SPatrick Williams querystdexec::__connect::connect_t3655cee9157SPatrick Williams static constexpr auto query(forwarding_query_t) noexcept -> bool 3665cee9157SPatrick Williams { 3675cee9157SPatrick Williams return false; 3685cee9157SPatrick Williams } 3695cee9157SPatrick Williams }; 3705cee9157SPatrick Williams } // namespace __connect 3715cee9157SPatrick Williams 3725cee9157SPatrick Williams using __connect::connect_t; 3735cee9157SPatrick Williams inline constexpr __connect::connect_t connect{}; 3745cee9157SPatrick Williams 3755cee9157SPatrick Williams ///////////////////////////////////////////////////////////////////////////// 3765cee9157SPatrick Williams // [exec.snd] 3775cee9157SPatrick Williams template <class _Sender, class _Receiver> 3785cee9157SPatrick Williams concept sender_to = // 3795cee9157SPatrick Williams receiver<_Receiver> // 3805cee9157SPatrick Williams && sender_in<_Sender, env_of_t<_Receiver>> // 3815cee9157SPatrick Williams && __receiver_from<_Receiver, _Sender> // 3825cee9157SPatrick Williams && requires(_Sender&& __sndr, _Receiver&& __rcvr) { 3835cee9157SPatrick Williams connect(static_cast<_Sender&&>(__sndr), 3845cee9157SPatrick Williams static_cast<_Receiver&&>(__rcvr)); 3855cee9157SPatrick Williams }; 3865cee9157SPatrick Williams 3875cee9157SPatrick Williams template <class _Tag, class... _Args> 3885cee9157SPatrick Williams auto __tag_of_sig_(_Tag (*)(_Args...)) -> _Tag; 3895cee9157SPatrick Williams template <class _Sig> 3905cee9157SPatrick Williams using __tag_of_sig_t = 3915cee9157SPatrick Williams decltype(stdexec::__tag_of_sig_(static_cast<_Sig*>(nullptr))); 3925cee9157SPatrick Williams 3935cee9157SPatrick Williams template <class _Sender, class _SetSig, class _Env = empty_env> 3945cee9157SPatrick Williams concept sender_of = // 3955cee9157SPatrick Williams sender_in<_Sender, _Env> // 3965cee9157SPatrick Williams && 3975cee9157SPatrick Williams same_as< 3985cee9157SPatrick Williams __types<_SetSig>, 3995cee9157SPatrick Williams __gather_completions_of< 4005cee9157SPatrick Williams __tag_of_sig_t<_SetSig>, _Sender, _Env, 4015cee9157SPatrick Williams __mcompose_q<__types, __qf<__tag_of_sig_t<_SetSig>>::template __f>, 4025cee9157SPatrick Williams __mconcat<__qq<__types>>>>; 4035cee9157SPatrick Williams 4045cee9157SPatrick Williams template <class _Error> 4055cee9157SPatrick Williams requires false 4065cee9157SPatrick Williams using __nofail_t = _Error; 4075cee9157SPatrick Williams 4085cee9157SPatrick Williams template <class _Sender, class _Env = empty_env> 4095cee9157SPatrick Williams concept __nofail_sender = 4105cee9157SPatrick Williams sender_in<_Sender, _Env> && 4115cee9157SPatrick Williams requires { 4125cee9157SPatrick Williams typename __gather_completion_signatures< 4135cee9157SPatrick Williams __completion_signatures_of_t<_Sender, _Env>, set_error_t, 4145cee9157SPatrick Williams __nofail_t, __sigs::__default_completion, __types>; 4155cee9157SPatrick Williams }; 4165cee9157SPatrick Williams 4175cee9157SPatrick Williams ///////////////////////////////////////////////////////////////////////////// 4185cee9157SPatrick Williams // early sender type-checking 4195cee9157SPatrick Williams template <class _Sender> 4205cee9157SPatrick Williams concept __well_formed_sender = __detail::__well_formed_sender<__minvoke< 4215cee9157SPatrick Williams __with_default_q<__completion_signatures_of_t, dependent_completions>, 4225cee9157SPatrick Williams _Sender>>; 4235cee9157SPatrick Williams } // namespace stdexec 424