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