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 // include these after __execution_fwd.hpp
21 #include "__basic_sender.hpp"
22 #include "__concepts.hpp"
23 #include "__domain.hpp"
24 #include "__env.hpp"
25 #include "__meta.hpp"
26 #include "__sender_adaptor_closure.hpp"
27 #include "__senders.hpp"
28 #include "__transform_completion_signatures.hpp"
29 #include "__transform_sender.hpp"
30 #include "__utility.hpp"
31 
32 #include <exception>
33 #include <tuple>
34 #include <variant>
35 
36 namespace stdexec
37 {
38 /////////////////////////////////////////////////////////////////////////////
39 // [execution.senders.adaptors.into_variant]
40 namespace __into_variant
41 {
42 template <class _Sender, class _Env>
43     requires sender_in<_Sender, _Env>
44 using __into_variant_result_t = value_types_of_t<_Sender, _Env>;
45 
46 template <class _Sender, class... _Env>
47 using __variant_t =
48     __value_types_t<__completion_signatures_of_t<_Sender, _Env...>>;
49 
50 template <class _Variant>
51 using __variant_completions =
52     completion_signatures<set_value_t(_Variant),
53                           set_error_t(std::exception_ptr)>;
54 
55 template <class _Sender, class... _Env>
56 using __completions = //
57     transform_completion_signatures<
58         __completion_signatures_of_t<_Sender, _Env...>,
59         __meval<__variant_completions, __variant_t<_Sender, _Env...>>,
60         __mconst<completion_signatures<>>::__f>;
61 
62 struct into_variant_t
63 {
64     template <sender _Sender>
operator ()stdexec::__into_variant::into_variant_t65     auto operator()(_Sender&& __sndr) const -> __well_formed_sender auto
66     {
67         auto __domain = __get_early_domain(__sndr);
68         return stdexec::transform_sender(
69             __domain,
70             __make_sexpr<into_variant_t>(__(), static_cast<_Sender&&>(__sndr)));
71     }
72 
73     STDEXEC_ATTRIBUTE((always_inline))
operator ()stdexec::__into_variant::into_variant_t74     auto operator()() const noexcept -> __binder_back<into_variant_t>
75     {
76         return {{}, {}, {}};
77     }
78 };
79 
80 struct __into_variant_impl : __sexpr_defaults
81 {
82     static constexpr auto get_state = //
83         []<class _Self, class _Receiver>(_Self&&, _Receiver&) noexcept {
84             using __variant_t =
85                 value_types_of_t<__child_of<_Self>, env_of_t<_Receiver>>;
86             return __mtype<__variant_t>();
87         };
88 
89     static constexpr auto complete = //
90         []<class _State, class _Receiver, class _Tag, class... _Args>(
91             __ignore, _State, _Receiver& __rcvr, _Tag,
92             _Args&&... __args) noexcept -> void {
93         if constexpr (__same_as<_Tag, set_value_t>)
94         {
95             using __variant_t = __t<_State>;
96             try
97             {
98                 set_value(static_cast<_Receiver&&>(__rcvr),
99                           __variant_t{std::tuple<_Args&&...>{
100                               static_cast<_Args&&>(__args)...}});
101             }
102             catch (...)
103             {
104                 stdexec::set_error(static_cast<_Receiver&&>(__rcvr),
105                                    std::current_exception());
106             }
107         }
108         else
109         {
110             _Tag()(static_cast<_Receiver&&>(__rcvr),
111                    static_cast<_Args&&>(__args)...);
112         }
113     };
114 
115     static constexpr auto get_completion_signatures =               //
116         []<class _Self, class... _Env>(_Self&&, _Env&&...) noexcept //
117         -> __completions<__child_of<_Self>, _Env...> {
118         static_assert(sender_expr_for<_Self, into_variant_t>);
119         return {};
120     };
121 };
122 } // namespace __into_variant
123 
124 using __into_variant::into_variant_t;
125 inline constexpr into_variant_t into_variant{};
126 
127 template <>
128 struct __sexpr_impl<into_variant_t> : __into_variant::__into_variant_impl
129 {};
130 } // namespace stdexec
131