1 /* 2 * Copyright (c) 2021-2024 NVIDIA Corporation 3 * 4 * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * https://llvm.org/LICENSE.txt 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include "__execution_fwd.hpp" 19 20 namespace stdexec { 21 namespace __detail { 22 // Accessor for the "data" field of a sender 23 struct __get_data { 24 template <class _Data> STDEXEC_ATTRIBUTEstdexec::__detail::__get_data25 STDEXEC_ATTRIBUTE(always_inline) 26 auto operator()(__ignore, _Data&& __data, auto&&...) const noexcept -> _Data&& { 27 return static_cast<_Data&&>(__data); 28 } 29 }; 30 31 // A function object that is to senders what std::apply is to tuples: 32 struct __sexpr_apply_t { 33 template <class _Sender, class _ApplyFn> STDEXEC_ATTRIBUTEstdexec::__detail::__sexpr_apply_t34 STDEXEC_ATTRIBUTE(always_inline) 35 auto operator()(_Sender&& __sndr, _ApplyFn&& __fun) const 36 noexcept(noexcept(__sndr 37 .apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun)))) 38 -> decltype(__sndr 39 .apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun))) { 40 return __sndr.apply(static_cast<_Sender&&>(__sndr), static_cast<_ApplyFn&&>(__fun)); 41 } 42 }; 43 44 // A type that describes a sender's metadata 45 template <class _Tag, class _Data, class... _Child> 46 struct __desc { 47 using __tag = _Tag; 48 using __data = _Data; 49 using __children = __types<_Child...>; 50 51 template <class _Fn> 52 using __f = __minvoke<_Fn, _Tag, _Data, _Child...>; 53 }; 54 55 template <class _Fn> 56 struct __sexpr_uncurry_fn { 57 template <class _Tag, class _Data, class... _Child> 58 constexpr auto operator()(_Tag, _Data&&, _Child&&...) const noexcept 59 -> __minvoke<_Fn, _Tag, _Data, _Child...>; 60 }; 61 62 template <class _CvrefSender, class _Fn> 63 using __sexpr_uncurry = __call_result_t<__sexpr_apply_t, _CvrefSender, __sexpr_uncurry_fn<_Fn>>; 64 65 template <class _Sender> 66 using __desc_of = __sexpr_uncurry<_Sender, __q<__desc>>; 67 68 using __get_desc = __sexpr_uncurry_fn<__q<__desc>>; 69 } // namespace __detail 70 71 using __detail::__sexpr_apply_t; 72 inline constexpr __sexpr_apply_t __sexpr_apply{}; 73 74 template <class _Sender, class _ApplyFn> 75 using __sexpr_apply_result_t = __call_result_t<__sexpr_apply_t, _Sender, _ApplyFn>; 76 77 template <class _Sender> 78 using tag_of_t = __detail::__desc_of<_Sender>::__tag; 79 80 template <class _Sender> 81 using __data_of = __detail::__desc_of<_Sender>::__data; 82 83 template <class _Sender, class _Continuation = __q<__types>> 84 using __children_of = __mapply<_Continuation, typename __detail::__desc_of<_Sender>::__children>; 85 86 template <class _Ny, class _Sender> 87 using __nth_child_of = __children_of<_Sender, __mbind_front_q<__m_at, _Ny>>; 88 89 template <std::size_t _Ny, class _Sender> 90 using __nth_child_of_c = __children_of<_Sender, __mbind_front_q<__m_at, __msize_t<_Ny>>>; 91 92 template <class _Sender> 93 using __child_of = __children_of<_Sender, __q<__mfront>>; 94 95 template <class _Sender> 96 inline constexpr std::size_t __nbr_children_of = __v<__children_of<_Sender, __msize>>; 97 98 template <class _Tp> 99 requires __mvalid<tag_of_t, _Tp> 100 struct __muncurry_<_Tp> { 101 template <class _Fn> 102 using __f = __detail::__sexpr_uncurry<_Tp, _Fn>; 103 }; 104 105 template <class _Sender> 106 concept sender_expr = __mvalid<tag_of_t, _Sender>; 107 108 template <class _Sender, class _Tag> 109 concept sender_expr_for = sender_expr<_Sender> && same_as<tag_of_t<_Sender>, _Tag>; 110 } // namespace stdexec 111