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 { 22 namespace __detail 23 { 24 // A function object that is to senders what std::apply is to tuples: 25 struct __sexpr_apply_t 26 { 27 template <class _Sender, class _ApplyFn> 28 STDEXEC_ATTRIBUTE((always_inline)) operator ()stdexec::__detail::__sexpr_apply_t29 auto operator()(_Sender&& __sndr, _ApplyFn&& __fun) const // 30 noexcept(noexcept(__sndr.apply(static_cast<_Sender&&>(__sndr), 31 static_cast<_ApplyFn&&>(__fun)))) // 32 -> decltype(__sndr.apply(static_cast<_Sender&&>(__sndr), 33 static_cast<_ApplyFn&&>(__fun))) 34 { 35 return __sndr.apply(static_cast<_Sender&&>(__sndr), 36 static_cast<_ApplyFn&&>(__fun)); // 37 } 38 }; 39 40 // A type that describes a sender's metadata 41 template <class _Tag, class _Data, class... _Child> 42 struct __desc 43 { 44 using __tag = _Tag; 45 using __data = _Data; 46 using __children = __types<_Child...>; 47 48 template <class _Fn> 49 using __f = __minvoke<_Fn, _Tag, _Data, _Child...>; 50 }; 51 52 template <class _Fn> 53 struct __sexpr_uncurry_fn 54 { 55 template <class _Tag, class _Data, class... _Child> 56 constexpr auto operator()(_Tag, _Data&&, _Child&&...) const noexcept 57 -> __minvoke<_Fn, _Tag, _Data, _Child...>; 58 }; 59 60 template <class _CvrefSender, class _Fn> 61 using __sexpr_uncurry = 62 __call_result_t<__sexpr_apply_t, _CvrefSender, __sexpr_uncurry_fn<_Fn>>; 63 64 template <class _Sender> 65 using __desc_of = __sexpr_uncurry<_Sender, __q<__desc>>; 66 67 using __get_desc = __sexpr_uncurry_fn<__q<__desc>>; 68 } // namespace __detail 69 70 using __detail::__sexpr_apply_t; 71 inline constexpr __sexpr_apply_t __sexpr_apply{}; 72 73 template <class _Sender, class _ApplyFn> 74 using __sexpr_apply_result_t = 75 __call_result_t<__sexpr_apply_t, _Sender, _ApplyFn>; 76 77 template <class _Sender> 78 using tag_of_t = typename __detail::__desc_of<_Sender>::__tag; 79 80 template <class _Sender> 81 using __data_of = typename __detail::__desc_of<_Sender>::__data; 82 83 template <class _Sender, class _Continuation = __q<__types>> 84 using __children_of = // 85 __mapply<_Continuation, typename __detail::__desc_of<_Sender>::__children>; 86 87 template <class _Ny, class _Sender> 88 using __nth_child_of = __children_of<_Sender, __mbind_front_q<__m_at, _Ny>>; 89 90 template <std::size_t _Ny, class _Sender> 91 using __nth_child_of_c = 92 __children_of<_Sender, __mbind_front_q<__m_at, __msize_t<_Ny>>>; 93 94 template <class _Sender> 95 using __child_of = __children_of<_Sender, __q<__mfront>>; 96 97 template <class _Sender> 98 inline constexpr std::size_t __nbr_children_of = 99 __v<__children_of<_Sender, __msize>>; 100 101 template <class _Tp> 102 requires __mvalid<tag_of_t, _Tp> 103 struct __muncurry_<_Tp> 104 { 105 template <class _Fn> 106 using __f = __detail::__sexpr_uncurry<_Tp, _Fn>; 107 }; 108 109 template <class _Sender> 110 concept sender_expr = // 111 __mvalid<tag_of_t, _Sender>; 112 113 template <class _Sender, class _Tag> 114 concept sender_expr_for = // 115 sender_expr<_Sender> && same_as<tag_of_t<_Sender>, _Tag>; 116 } // namespace stdexec 117