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