di 0.1.0
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&
64 requires(has_base)
65 {
66 return this->m_base.value;
67 }
68 auto base() const& -> Base const&
69 requires(has_base)
70 {
71 return this->m_base.value;
72 }
73 auto base() && -> Base&& requires(has_base) {
74 return util::move(this->m_base).value;
75 } auto base() const&& -> Base const&&
76 requires(has_base)
77 {
78 return util::move(this->m_base).value;
79 }
80
81 public:
82 using is_receiver = void;
83
84 Type() = default;
85
86 template<typename T>
87 requires(has_base && concepts::ConstructibleFrom<Base, T>)
88 explicit Type(T&& value) : m_base(util::forward<T>(value)) {}
89
90 private:
91 // The following mechanism is used to forward the set_value, set_error,
92 // set_stopped, and get_env CPOs to either the base receiver or a
93 // member function in Self. Forwarding directly to the base receiver
94 // is only done when the corresponding member function is not defined.
95 // This is detected by having these variables of the same name in this
96 // class, and then seeing if they are properly accessible through the
97 // derived Self class. Additionally, calls to the Self member functions
98 // must be done in a static templated method to prevent the compiler
99 // from interacting with them while Self is still an incomplete type.
100 // Additionally, the actually forwarding logic needs multiple redundant
101 // template parameters to defer evaluation of the function's constraints
102 // while Self is an incomplete type.
103 constexpr static int set_value = 1;
104 constexpr static int set_error = 1;
105 constexpr static int set_stopped = 1;
106 constexpr static int set_next = 1;
107 constexpr static int get_env = 1;
108
109 template<typename S>
110 constexpr static auto missing_set_value() -> bool {
111 return requires { requires bool(int(S::set_value)); };
112 }
113 template<typename S>
114 constexpr static auto missing_set_error() -> bool {
115 return requires { requires bool(int(S::set_error)); };
116 }
117 template<typename S>
118 constexpr static auto missing_set_stopped() -> bool {
119 return requires { requires bool(int(S::set_stopped)); };
120 }
121 template<typename S>
122 constexpr static auto missing_set_next() -> bool {
123 return requires { requires bool(int(S::set_next)); };
124 }
125 template<typename S>
126 constexpr static auto missing_get_env() -> bool {
127 return requires { requires bool(int(S::get_env)); };
128 }
129
130 template<typename S, typename... Args>
131 static auto do_set_value(S&& self, Args&&... args)
132 -> decltype(util::forward<S>(self).set_value(util::forward<Args>(args)...)) {
133 return util::forward<S>(self).set_value(util::forward<Args>(args)...);
134 }
135 template<typename S, typename... Args>
136 static auto do_set_error(S&& self, Args&&... args)
137 -> decltype(util::forward<S>(self).set_error(util::forward<Args>(args)...)) {
138 return util::forward<S>(self).set_error(util::forward<Args>(args)...);
139 }
140 template<typename S, typename... Args>
141 static auto do_set_stopped(S&& self, Args&&... args)
142 -> decltype(util::forward<S>(self).set_stopped(util::forward<Args>(args)...)) {
143 return util::forward<S>(self).set_stopped(util::forward<Args>(args)...);
144 }
145 template<typename S, typename... Args>
146 static auto do_set_next(S& self, Args&&... args) -> decltype(self.set_next(util::forward<Args>(args)...)) {
147 return self.set_next(util::forward<Args>(args)...);
148 }
149 template<typename S, typename... Args>
150 static auto do_get_env(S&& self, Args&&... args)
151 -> decltype(util::forward<S>(self).get_env(util::forward<Args>(args)...)) {
152 return util::forward<S>(self).get_env(util::forward<Args>(args)...);
153 }
154
155 template<concepts::SameAs<SetValue> Tag, typename S = Self, typename... Args>
156 friend void tag_invoke(Tag, Self&& self, Args&&... args)
157 requires(
158 requires { Type::do_set_value(util::move(self), util::forward<Args>(args)...); } ||
159 requires {
160 requires missing_set_value<S>();
161 execution::set_value(Type::get_base(util::move(self)), util::forward<Args>(args)...);
162 })
163 {
164 if constexpr (requires { Type::do_set_value(util::move(self), util::forward<Args>(args)...); }) {
165 Type::do_set_value(util::move(self), util::forward<Args>(args)...);
166 } else {
167 execution::set_value(Type::get_base(util::move(self)), util::forward<Args>(args)...);
168 }
169 }
170
171 template<concepts::SameAs<SetError> Tag, typename Arg, typename S = Self>
172 friend void tag_invoke(Tag, Self&& self, Arg&& arg)
173 requires(
174 requires { Type::do_set_error(util::move(self), util::forward<Arg>(arg)); } ||
175 requires {
176 requires missing_set_error<S>();
177 execution::set_error(Type::get_base(util::move(self)), util::forward<Arg>(arg));
178 })
179 {
180 if constexpr (requires { Type::do_set_error(util::move(self), util::forward<Arg>(arg)); }) {
181 Type::do_set_error(util::move(self), util::forward<Arg>(arg));
182 } else {
183 execution::set_error(Type::get_base(util::move(self)), util::forward<Arg>(arg));
184 }
185 }
186
187 template<concepts::SameAs<SetStopped> Tag, typename S = Self>
188 friend void tag_invoke(Tag, Self&& self)
189 requires(
190 requires { Type::do_set_stopped(util::move(self)); } ||
191 requires {
192 requires missing_set_stopped<S>();
193 execution::set_stopped(Type::get_base(util::move(self)));
194 })
195 {
196 if constexpr (requires { Type::do_set_stopped(util::move(self)); }) {
197 Type::do_set_stopped(util::move(self));
198 } else {
199 execution::set_stopped(Type::get_base(util::move(self)));
200 }
201 }
202
203 template<concepts::SameAs<types::Tag<execution::set_next>> Tag, typename N, typename S = Self>
204 friend auto tag_invoke(Tag, Self& self, N&& next) -> decltype(auto)
205 requires(
206 requires { Type::do_set_next(self, util::forward<N>(next)); } ||
207 requires {
208 requires missing_set_next<S>();
209 execution::set_next(Type::get_base(self), util::forward<N>(next));
210 })
211 {
212 if constexpr (requires { Type::do_set_next(self, util::forward<N>(next)); }) {
213 return Type::do_set_next(self, util::forward<N>(next));
214 } else {
215 return execution::set_next(Type::get_base(self), util::forward<N>(next));
216 }
217 }
218
219 template<concepts::SameAs<types::Tag<execution::get_env>> Tag, typename S = Self>
220 friend auto tag_invoke(Tag, Self const& self) -> decltype(auto)
221 requires(
222 requires { Type::do_get_env(util::move(self)); } ||
223 requires {
224 requires missing_get_env<S>();
225 execution::get_env(Type::get_base(self));
226 })
227 {
228 if constexpr (requires { Type::do_get_env(util::move(self)); }) {
229 return Type::do_get_env(util::move(self));
230 } else {
231 return make_env(execution::get_env(Type::get_base(self)));
232 }
233 }
234
235 [[no_unique_address]] util::StoreIf<Base, has_base> m_base;
236 };
237 };
238}
239
240template<concepts::ClassType Self, concepts::Receiver Base = receiver_interface_ns::fake_receiver::FakeReceiver>
242}
243
244namespace di {
246}
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:241
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 any_storable.h:9
constexpr auto next
Definition next.h:35
constexpr tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
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:204
void is_receiver
Definition receiver_adaptor.h:82
friend void tag_invoke(Tag, Self &&self, Args &&... args)
Definition receiver_adaptor.h:156
friend void tag_invoke(Tag, Self &&self, Arg &&arg)
Definition receiver_adaptor.h:172
friend void tag_invoke(Tag, Self &&self)
Definition receiver_adaptor.h:188
Type(T &&value)
Definition receiver_adaptor.h:88
Definition function.h:30