Iros
 
Loading...
Searching...
No Matches
receiver_adaptor.h
Go to the documentation of this file.
1#pragma once
2
11#include "di/meta/util.h"
12#include "di/util/store_if.h"
14
15namespace di::execution {
25
26 template<typename T, typename U>
28 auto c_style_cast(U&& u) noexcept -> meta::Like<U&&, T> {
30 return (meta::Like<U&&, T>) util::forward<U>(u);
31 }
32
33 template<typename Self, typename Base>
35 struct Type {
36 private:
37 friend Self;
38
39 constexpr static bool has_base = !concepts::SameAs<Base, fake_receiver::FakeReceiver>;
40
41 template<typename S>
42 using GetDerivedBase = decltype(util::declval<S>().base());
43
44 using BaseTypeImpl =
46
47 template<typename S>
48 using BaseType = meta::Invoke<BaseTypeImpl, S&&>;
49
50 // The base receiver is either stored in the adaptor itself, or in the
51 // derived class. The type of this function must be explicitly provided,
52 // since it cannot be deduced (in the case where there is a member base()
53 // function, since Self is currently incomplete).
54 template<typename S>
55 static auto get_base(S&& self) -> BaseType<S> {
56 if constexpr (!has_base) {
57 return util::forward<S>(self).base();
58 } else {
59 return c_style_cast<Type>(util::forward<S>(self)).base();
60 }
61 }
62
63 auto base() & -> Base& requires(has_base) { return this->m_base.value; } auto base() const& -> Base const&
64 requires(has_base)
65 {
66 return this->m_base.value;
67 }
68 auto base() && -> Base&& requires(has_base) {
69 return util::move(this->m_base).value;
70 } auto base() const&& -> Base const&&
71 requires(has_base)
72 {
73 return util::move(this->m_base).value;
74 }
75
76 public:
77 using is_receiver = void;
78
79 Type() = default;
80
81 template<typename T>
82 requires(has_base && concepts::ConstructibleFrom<Base, T>)
83 explicit Type(T&& value) : m_base(util::forward<T>(value)) {}
84
85 private:
86 // The following mechanism is used to forward the set_value, set_error,
87 // set_stopped, and get_env CPOs to either the base receiver or a
88 // member function in Self. Forwarding directly to the base receiver
89 // is only done when the corresponding member function is not defined.
90 // This is detected by having these variables of the same name in this
91 // class, and then seeing if they are properly accessible through the
92 // derived Self class. Additionally, calls to the Self member functions
93 // must be done in a static templated method to prevent the compiler
94 // from interacting with them while Self is still an incomplete type.
95 // Additionally, the actually forwarding logic needs multiple redundant
96 // template parameters to defer evaluation of the function's constraints
97 // while Self is an incomplete type.
98 constexpr static int set_value = 1;
99 constexpr static int set_error = 1;
100 constexpr static int set_stopped = 1;
101 constexpr static int set_next = 1;
102 constexpr static int get_env = 1;
103
104 template<typename S>
105 constexpr static auto missing_set_value() -> bool {
106 return requires { requires bool(int(S::set_value)); };
107 }
108 template<typename S>
109 constexpr static auto missing_set_error() -> bool {
110 return requires { requires bool(int(S::set_error)); };
111 }
112 template<typename S>
113 constexpr static auto missing_set_stopped() -> bool {
114 return requires { requires bool(int(S::set_stopped)); };
115 }
116 template<typename S>
117 constexpr static auto missing_set_next() -> bool {
118 return requires { requires bool(int(S::set_next)); };
119 }
120 template<typename S>
121 constexpr static auto missing_get_env() -> bool {
122 return requires { requires bool(int(S::get_env)); };
123 }
124
125 template<typename S, typename... Args>
126 static auto do_set_value(S&& self, Args&&... args)
127 -> decltype(util::forward<S>(self).set_value(util::forward<Args>(args)...)) {
128 return util::forward<S>(self).set_value(util::forward<Args>(args)...);
129 }
130 template<typename S, typename... Args>
131 static auto do_set_error(S&& self, Args&&... args)
132 -> decltype(util::forward<S>(self).set_error(util::forward<Args>(args)...)) {
133 return util::forward<S>(self).set_error(util::forward<Args>(args)...);
134 }
135 template<typename S, typename... Args>
136 static auto do_set_stopped(S&& self, Args&&... args)
137 -> decltype(util::forward<S>(self).set_stopped(util::forward<Args>(args)...)) {
138 return util::forward<S>(self).set_stopped(util::forward<Args>(args)...);
139 }
140 template<typename S, typename... Args>
141 static auto do_set_next(S& self, Args&&... args) -> decltype(self.set_next(util::forward<Args>(args)...)) {
142 return self.set_next(util::forward<Args>(args)...);
143 }
144 template<typename S, typename... Args>
145 static auto do_get_env(S&& self, Args&&... args)
146 -> decltype(util::forward<S>(self).get_env(util::forward<Args>(args)...)) {
147 return util::forward<S>(self).get_env(util::forward<Args>(args)...);
148 }
149
150 template<concepts::SameAs<SetValue> Tag, typename S = Self, typename... Args>
151 friend void tag_invoke(Tag, Self&& self, Args&&... args)
152 requires(
153 requires { Type::do_set_value(util::move(self), util::forward<Args>(args)...); } ||
154 requires {
155 requires missing_set_value<S>();
156 execution::set_value(Type::get_base(util::move(self)), util::forward<Args>(args)...);
157 })
158 {
159 if constexpr (requires { Type::do_set_value(util::move(self), util::forward<Args>(args)...); }) {
160 Type::do_set_value(util::move(self), util::forward<Args>(args)...);
161 } else {
162 execution::set_value(Type::get_base(util::move(self)), util::forward<Args>(args)...);
163 }
164 }
165
166 template<concepts::SameAs<SetError> Tag, typename Arg, typename S = Self>
167 friend void tag_invoke(Tag, Self&& self, Arg&& arg)
168 requires(
169 requires { Type::do_set_error(util::move(self), util::forward<Arg>(arg)); } ||
170 requires {
171 requires missing_set_error<S>();
172 execution::set_error(Type::get_base(util::move(self)), util::forward<Arg>(arg));
173 })
174 {
175 if constexpr (requires { Type::do_set_error(util::move(self), util::forward<Arg>(arg)); }) {
176 Type::do_set_error(util::move(self), util::forward<Arg>(arg));
177 } else {
178 execution::set_error(Type::get_base(util::move(self)), util::forward<Arg>(arg));
179 }
180 }
181
182 template<concepts::SameAs<SetStopped> Tag, typename S = Self>
183 friend void tag_invoke(Tag, Self&& self)
184 requires(
185 requires { Type::do_set_stopped(util::move(self)); } ||
186 requires {
187 requires missing_set_stopped<S>();
188 execution::set_stopped(Type::get_base(util::move(self)));
189 })
190 {
191 if constexpr (requires { Type::do_set_stopped(util::move(self)); }) {
192 Type::do_set_stopped(util::move(self));
193 } else {
194 execution::set_stopped(Type::get_base(util::move(self)));
195 }
196 }
197
198 template<concepts::SameAs<types::Tag<execution::set_next>> Tag, typename N, typename S = Self>
199 friend auto tag_invoke(Tag, Self& self, N&& next) -> decltype(auto)
200 requires(
201 requires { Type::do_set_next(self, util::forward<N>(next)); } ||
202 requires {
203 requires missing_set_next<S>();
204 execution::set_next(Type::get_base(self), util::forward<N>(next));
205 })
206 {
207 if constexpr (requires { Type::do_set_next(self, util::forward<N>(next)); }) {
208 return Type::do_set_next(self, util::forward<N>(next));
209 } else {
210 return execution::set_next(Type::get_base(self), util::forward<N>(next));
211 }
212 }
213
214 template<concepts::SameAs<types::Tag<execution::get_env>> Tag, typename S = Self>
215 friend auto tag_invoke(Tag, Self const& self) -> decltype(auto)
216 requires(
217 requires { Type::do_get_env(util::move(self)); } ||
218 requires {
219 requires missing_get_env<S>();
220 execution::get_env(Type::get_base(self));
221 })
222 {
223 if constexpr (requires { Type::do_get_env(util::move(self)); }) {
224 return Type::do_get_env(util::move(self));
225 } else {
226 return make_env(execution::get_env(Type::get_base(self)));
227 }
228 }
229
230 [[no_unique_address]] util::StoreIf<Base, has_base> m_base;
231 };
232 };
233}
234
235template<concepts::ClassType Self, concepts::Receiver Base = receiver_interface_ns::fake_receiver::FakeReceiver>
237}
238
239namespace di {
241}
Definition language.h:373
Definition operations.h:11
Definition util.h:47
Definition core.h:114
Definition receiver_adaptor.h:16
auto c_style_cast(U &&u) noexcept -> meta::Like< U &&, T >
Definition receiver_adaptor.h:28
Definition bulk.h:30
constexpr auto set_error
Definition set_error.h:14
constexpr auto set_next
Set the next sender of a sequence.
Definition sequence_sender.h:77
constexpr auto make_env
Create an environment with overrides for queries.
Definition make_env.h:147
meta::Type< receiver_interface_ns::ReceiverAdaptor< Self, Base > > ReceiverAdaptor
Definition receiver_adaptor.h:236
constexpr auto set_stopped
Definition set_stopped.h:14
constexpr auto next
Get the next value of a async range in a coroutine.
Definition async_range.h:52
constexpr auto get_env
Definition get_env.h:27
constexpr auto set_value
Definition set_value.h:14
detail::ConditionalHelper< value, T, U >::Type Conditional
Definition core.h:88
T::Type Type
Definition core.h:26
Type< detail::LikeHelper< T, U > > Like
Definition language.h:468
Type< Defer< Fun::template Invoke, Args... > > Invoke
Definition function.h:43
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
auto declval() -> meta::AddRValueReference< T >
Definition declval.h:8
StatusCode< Erased< long > > Error
Definition error.h:8
Definition zstring_parser.h:9
constexpr auto next
Definition next.h:35
constexpr tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
@ S
Definition key.h:28
Defines the sequence sender concepts and related CPOs.
Definition set_error.h:6
Definition set_stopped.h:6
Definition set_value.h:6
friend auto tag_invoke(Tag, Self &self, N &&next) -> decltype(auto) requires(
Definition receiver_adaptor.h:199
void is_receiver
Definition receiver_adaptor.h:77
friend void tag_invoke(Tag, Self &&self, Args &&... args)
Definition receiver_adaptor.h:151
friend void tag_invoke(Tag, Self &&self, Arg &&arg)
Definition receiver_adaptor.h:167
friend void tag_invoke(Tag, Self &&self)
Definition receiver_adaptor.h:183
Type(T &&value)
Definition receiver_adaptor.h:83
Definition function.h:30