di 0.1.0
Loading...
Searching...
No Matches
expected.h
Go to the documentation of this file.
1#pragma once
2
5#include "di/meta/core.h"
6#include "di/meta/language.h"
8#include "di/meta/trivial.h"
9#include "di/meta/util.h"
10#include "di/meta/vocab.h"
11#include "di/util/addressof.h"
13#include "di/util/destroy_at.h"
14#include "di/util/forward.h"
16#include "di/util/move.h"
23
24namespace di::vocab {
25namespace detail {
26 template<typename Expected, typename From, typename To>
27 concept ConvertibleToWorkaround =
28 !concepts::SameAs<Expected, meta::RemoveCVRef<From>> && concepts::ConvertibleTo<From, To>;
29}
30
31template<typename T, typename E>
32requires(!concepts::LanguageVoid<T> && !concepts::LanguageVoid<E>)
33class [[nodiscard]] Expected<T, E> : public function::monad::MonadInterface<Expected<T, E>> {
34public:
35 using Value = T;
36 using Error = E;
37
38 constexpr Expected()
40 : m_value() {}
41
42 constexpr Expected(Expected const&) = default;
43 constexpr Expected(Expected&&) = default;
44
45 constexpr Expected(Expected const&)
47 = delete;
48
55
62
63 template<typename U, typename G>
65 concepts::ConstructibleFrom<E, G const&> && concepts::detail::ExpectedCanConvertConstructor<T, E, U, G>)
68 internal_construct_from_expected(other);
69 }
70
71 template<typename U, typename G>
73 concepts::ConstructibleFrom<E, G> && concepts::detail::ExpectedCanConvertConstructor<T, E, U, G>)
76 internal_construct_from_expected(util::move(other));
77 }
78
79 template<typename U = T>
82 constexpr explicit(!detail::ConvertibleToWorkaround<Expected, U, T>) Expected(U&& value)
83 : m_value(util::forward<U>(value)) {}
84
85 template<typename G>
88 : m_has_error(true), m_error(error.error()) {}
89
90 template<typename G>
93 : m_has_error(true), m_error(util::move(error).error()) {}
94
95 template<typename... Args>
96 requires(concepts::ConstructibleFrom<T, Args...>)
97 constexpr explicit Expected(types::InPlace, Args&&... args)
98 : m_value(types::in_place, util::forward<Args>(args)...) {}
99
100 template<typename U, typename... Args>
102 constexpr explicit Expected(types::InPlace, std::initializer_list<U> list, Args&&... args)
103 : m_value(types::in_place, list, util::forward<Args>(args)...) {}
104
105 template<typename... Args>
106 requires(concepts::ConstructibleFrom<E, Args...>)
107 constexpr explicit Expected(types::Unexpect, Args&&... args)
108 : m_has_error(true), m_error(types::in_place, util::forward<Args>(args)...) {}
109
110 template<typename U, typename... Args>
112 constexpr explicit Expected(types::Unexpect, std::initializer_list<U> list, Args&&... args)
113 : m_has_error(true), m_error(types::in_place, list, util::forward<Args>(args)...) {}
114
115 constexpr ~Expected() = default;
116
117 constexpr ~Expected()
119 {
120 internal_reset();
121 }
122
123 constexpr auto operator=(Expected const& other) -> Expected&
125 {
126 return internal_assign_from_expected(other);
127 }
128
129 constexpr auto operator=(Expected&& other) -> Expected&
131 {
132 return internal_assign_from_expected(util::move(other));
133 }
134
135 template<typename U = T>
137 constexpr auto operator=(U&& value) -> Expected& {
138 return internal_assign_from_value(util::forward<U>(value));
139 }
140
141 template<typename G>
143 constexpr auto operator=(Unexpected<G> const& error) -> Expected& {
144 return internal_assign_from_unexpected(error);
145 }
146
147 template<typename G>
149 constexpr auto operator=(Unexpected<G>&& error) -> Expected& {
150 return internal_assign_from_unexpected(util::move(error));
151 }
152
153 constexpr auto operator->() { return util::addressof(value()); }
154 constexpr auto operator->() const { return util::addressof(value()); }
155
156 constexpr auto operator*() & -> T& { return value(); }
157 constexpr auto operator*() const& -> T const& { return value(); }
158 constexpr auto operator*() && -> T&& { return util::move(*this).value(); }
159 constexpr auto operator*() const&& -> T const&& { return util::move(*this).value(); }
160
161 constexpr explicit operator bool() const { return has_value(); }
162 constexpr auto has_value() const -> bool { return !m_has_error; }
163
164 constexpr auto value() & -> T& {
166 return m_value.value();
167 }
168 constexpr auto value() const& -> T const& {
170 return m_value.value();
171 }
172 constexpr auto value() && -> T&& {
174 return util::move(m_value).value();
175 }
176 constexpr auto value() const&& -> T const&& {
178 return util::move(m_value).value();
179 }
180
181 constexpr auto error() & -> E& {
183 return m_error.value();
184 }
185 constexpr auto error() const& -> E const& {
187 return m_error.value();
188 }
189 constexpr auto error() && -> E&& {
191 return util::move(m_error).value();
192 }
193 constexpr auto error() const&& -> E const&& {
195 return util::move(m_error).value();
196 }
197
198 template<concepts::ConvertibleTo<T> U>
200 constexpr auto value_or(U&& default_value) const& -> T {
201 return has_value() ? **this : static_cast<T>(util::forward<U>(default_value));
202 }
203
204 template<concepts::ConvertibleTo<T> U>
206 constexpr auto value_or(U&& default_value) && -> T {
207 return has_value() ? *util::move(*this) : static_cast<T>(util::forward<U>(default_value));
208 }
209
210 constexpr auto optional_value() const& -> Optional<T>
211 requires(concepts::CopyConstructible<T>)
212 {
213 return has_value() ? Optional<T> { in_place, **this } : nullopt;
214 }
215
216 constexpr auto optional_value() && -> Optional<T>
218 {
219 return has_value() ? Optional<T> { in_place, *util::move(*this) } : nullopt;
220 }
221
222 template<typename... Args>
223 requires(concepts::ConstructibleFrom<T, Args...>)
224 constexpr auto emplace(Args&&... args) -> T& {
225 return internal_emplace(util::forward<Args>(args)...);
226 }
227
228 template<typename U, typename... Args>
230 constexpr auto emplace(std::initializer_list<U> list, Args&&... args) -> T& {
231 return internal_emplace(list, util::forward<Args>(args)...);
232 }
233
234 constexpr auto __try_did_fail() && -> Unexpected<E> {
235 return Unexpected<E> { in_place, util::move(*this).error() };
236 }
237 constexpr auto __try_did_succeed() && -> Expected { return Expected { in_place, util::move(*this).value() }; }
238 constexpr auto __try_move_out() && -> T&& { return util::move(*this).value(); }
239
240private:
241 template<typename U, typename G>
242 friend class Expected;
243
244 template<concepts::EqualityComparableWith<T> U, concepts::EqualityComparableWith<E> G>
245 constexpr friend auto operator==(Expected const& a, Expected<U, G> const& b) -> bool {
246 if (a.has_value() != b.has_value()) {
247 return false;
248 }
249 if (a.has_value() == b.has_value()) {
250 return a.value() == b.value();
251 }
252 return a.error() == b.error();
253 }
254
255 template<typename U>
257 constexpr friend auto operator==(Expected const& a, U const& b) -> bool {
258 return a.has_value() && a.value() == b;
259 }
260
261 template<concepts::EqualityComparableWith<E> G>
262 constexpr friend auto operator==(Expected const& a, Unexpected<G> const& b) -> bool {
263 return !a.has_value() && a.error() == b.error();
264 }
265
266 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
267 typename U = meta::UnwrapRefDecay<meta::InvokeResult<F, meta::Like<Self, T>>>>
269 constexpr friend auto tag_invoke(types::Tag<function::monad::fmap>, Self&& self, F&& function) -> Expected<U, E> {
270 if (!self) {
271 return Expected<U, E> { types::unexpect, util::forward<Self>(self).error() };
272 }
273 if constexpr (concepts::LanguageVoid<U>) {
274 function::invoke(util::forward<F>(function), util::forward<Self>(self).value());
275 return {};
276 } else {
277 return function::invoke(util::forward<F>(function), util::forward<Self>(self).value());
278 }
279 }
280
281 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
282 typename R = meta::InvokeResult<F, meta::Like<Self, T>>>
284 constexpr friend auto tag_invoke(types::Tag<function::monad::bind>, Self&& self, F&& function) -> R {
285 if (!self) {
286 return R { types::unexpect, util::forward<Self>(self).error() };
287 }
288 return function::invoke(util::forward<F>(function), util::forward<Self>(self).value());
289 }
290
291 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
292 typename R = meta::InvokeResult<F, meta::Like<Self, E>>>
294 constexpr friend auto tag_invoke(types::Tag<function::monad::fail>, Self&& self, F&& function) -> R {
295 if (self) {
296 return R { types::in_place, util::forward<Self>(self).value() };
297 }
298 return function::invoke(util::forward<F>(function), util::forward<Self>(self).error());
299 }
300
301 template<concepts::RemoveCVRefSameAs<Expected> Self, typename F,
302 typename G = meta::UnwrapRefDecay<meta::InvokeResult<F, meta::Like<Self, E>>>>
303 constexpr friend auto tag_invoke(types::Tag<function::monad::fmap_right>, Self&& self, F&& function)
304 -> Expected<T, G> {
305 if (self) {
306 return Expected<T, G> { types::in_place, util::forward<Self>(self).value() };
307 }
308 if constexpr (concepts::LanguageVoid<G>) {
309 function::invoke(util::forward<F>(function), util::forward<Self>(self).error());
310 return Expected<T, G> { types::in_place, util::forward<Self>(self).value() };
311 } else {
313 function::invoke(util::forward<F>(function), util::forward<Self>(self).error()) };
314 }
315 }
316
317 template<typename U>
318 constexpr void internal_construct_from_expected(U&& other) {
319 auto other_has_value = other.has_value();
320 if (other_has_value) {
321 util::construct_at(&this->m_value, di::forward<U>(other).value());
322 } else {
323 util::construct_at(&this->m_error, di::forward<U>(other).error());
324 }
325 this->m_has_error = !other_has_value;
326 }
327
328 constexpr void internal_reset() {
329 if (has_value()) {
330 util::destroy_at(&m_value);
331 } else {
332 util::destroy_at(&m_error);
333 }
334 }
335
336 template<typename U>
337 constexpr auto internal_assign_from_expected(U&& other) -> Expected& {
338 if (this->has_value() && other.has_value()) {
339 this->m_value = util::forward<U>(other).value();
340 } else if (this->has_value() && !other.has_value()) {
341 internal_reset();
342 util::construct_at(&this->m_error, util::forward<U>(other).error());
343 } else if (!this->has_value() && other.has_value()) {
344 internal_reset();
345 util::construct_at(&this->m_value, util::forward<U>(other).value());
346 } else {
347 this->m_error = util::forward<U>(other).error();
348 }
349 this->m_has_error = !other.has_value();
350 return *this;
351 }
352
353 template<typename U>
354 constexpr auto internal_assign_from_value(U&& value) -> Expected& {
355 if (this->has_value()) {
356 this->m_value = util::forward<U>(value);
357 } else {
358 internal_reset();
359 util::construct_at(&this->m_value, util::forward<U>(value));
360 }
361 this->m_has_error = false;
362 return *this;
363 }
364
365 template<typename U>
366 constexpr auto internal_assign_from_unexpected(U&& unexpected) -> Expected& {
367 if (this->has_value()) {
368 internal_reset();
369 util::construct_at(&this->m_error, util::forward<U>(unexpected).error());
370 } else {
371 this->m_error = util::forward<U>(unexpected).error();
372 }
373 this->m_has_error = true;
374 return *this;
375 }
376
377 template<typename... Args>
378 constexpr auto internal_emplace(Args&&... args) -> T& {
379 if (this->has_value()) {
380 m_value.emplace(util::forward<Args>(args)...);
381 } else {
382 internal_reset();
383 util::construct_at(&this->m_value, types::in_place, util::forward<Args>(args)...);
384 }
385 this->m_has_error = false;
386 return value();
387 }
388
389 template<typename U, typename... Args>
390 constexpr auto internal_emplace(std::initializer_list<U> list, Args&&... args) -> T& {
391 if (this->has_value()) {
392 m_value.emplace(list, util::forward<Args>(args)...);
393 } else {
394 internal_reset();
395 util::construct_at(&this->m_value, types::in_place, list, util::forward<Args>(args)...);
396 }
397 this->m_has_error = false;
398 return value();
399 }
400
401 bool m_has_error { false };
402 union {
405 };
406};
407}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition rebindable_box.h:42
E Error
Definition expected.h:36
constexpr friend auto tag_invoke(types::Tag< function::monad::fmap >, Self &&self, F &&function) -> Expected< U, E >
Definition expected.h:269
constexpr auto __try_move_out() &&-> T &&
Definition expected.h:238
constexpr auto has_value() const -> bool
Definition expected.h:162
constexpr auto value() &-> T &
Definition expected.h:164
constexpr G const & other
Definition expected.h:67
constexpr auto value_or(U &&default_value) const &-> T
Definition expected.h:200
constexpr auto operator*() &-> T &
Definition expected.h:156
constexpr Expected(types::InPlace, std::initializer_list< U > list, Args &&... args)
Definition expected.h:102
friend class Expected
Definition expected.h:242
constexpr auto optional_value() &&-> Optional< T > requires(concepts::MoveConstructible< T >)
Definition expected.h:216
constexpr friend auto tag_invoke(types::Tag< function::monad::fail >, Self &&self, F &&function) -> R
Definition expected.h:294
constexpr auto value_or(U &&default_value) &&-> T
Definition expected.h:206
constexpr auto emplace(Args &&... args) -> T &
Definition expected.h:224
constexpr auto operator*() &&-> T &&
Definition expected.h:158
constexpr auto value() const &&-> T const &&
Definition expected.h:176
constexpr auto operator*() const &-> T const &
Definition expected.h:157
constexpr Expected(types::InPlace, Args &&... args)
Definition expected.h:97
constexpr auto value() const &-> T const &
Definition expected.h:168
constexpr friend auto operator==(Expected const &a, Expected< U, G > const &b) -> bool
Definition expected.h:245
constexpr auto optional_value() const &-> Optional< T > requires(concepts::CopyConstructible< T >)
Definition expected.h:210
constexpr auto error() &&-> E &&
Definition expected.h:189
constexpr friend auto operator==(Expected const &a, Unexpected< G > const &b) -> bool
Definition expected.h:262
constexpr auto error() const &-> E const &
Definition expected.h:185
constexpr ~Expected()=default
constexpr Expected(Expected &&)=default
T Value
Definition expected.h:35
constexpr auto operator=(Expected const &other) -> Expected &requires(concepts::CopyConstructible< T > &&concepts::CopyConstructible< E >)
Definition expected.h:123
constexpr friend auto tag_invoke(types::Tag< function::monad::fmap_right >, Self &&self, F &&function) -> Expected< T, G >
Definition expected.h:303
constexpr auto value() &&-> T &&
Definition expected.h:172
constexpr Expected(Expected &&other)
Definition expected.h:56
util::RebindableBox< T > m_value
Definition expected.h:403
constexpr auto __try_did_succeed() &&-> Expected
Definition expected.h:237
constexpr auto error() const &&-> E const &&
Definition expected.h:193
constexpr auto emplace(std::initializer_list< U > list, Args &&... args) -> T &
Definition expected.h:230
constexpr Expected(Expected const &)=default
constexpr Expected(types::Unexpect, Args &&... args)
Definition expected.h:107
constexpr Expected(Expected const &)=delete
constexpr auto operator=(Expected &&other) -> Expected &requires(concepts::MoveConstructible< T > &&concepts::MoveConstructible< E >)
Definition expected.h:129
constexpr Expected(Expected const &other)
Definition expected.h:49
constexpr auto operator*() const &&-> T const &&
Definition expected.h:159
constexpr Expected()
Definition expected.h:38
constexpr ~Expected()
Definition expected.h:117
util::RebindableBox< E > m_error
Definition expected.h:404
constexpr auto __try_did_fail() &&-> Unexpected< E >
Definition expected.h:234
constexpr auto operator->()
Definition expected.h:153
constexpr Expected(types::Unexpect, std::initializer_list< U > list, Args &&... args)
Definition expected.h:112
constexpr friend auto tag_invoke(types::Tag< function::monad::bind >, Self &&self, F &&function) -> R
Definition expected.h:284
constexpr auto error() &-> E &
Definition expected.h:181
constexpr auto operator->() const
Definition expected.h:154
Definition expected_forward_declaration.h:8
Definition optional_forward_declaration.h:5
Definition unexpected.h:14
Definition operations.h:11
Definition operations.h:99
Definition operations.h:34
Definition operations.h:24
Definition vocab.h:30
Definition core.h:128
Definition operations.h:43
Definition core.h:114
Definition vocab.h:152
Definition any_storable.h:9
Definition as_bool.h:8
constexpr auto invoke
Definition invoke.h:100
constexpr auto value
Definition value.h:34
meta::RemoveCVRef< T >::Error ExpectedError
Definition vocab.h:38
constexpr auto ExpectedRank
Definition vocab.h:41
meta::RemoveCVRef< T >::Value ExpectedValue
Definition vocab.h:35
Definition method.h:5
constexpr auto in_place
Definition in_place.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto unexpect
Definition unexpect.h:8
Definition vocab.h:96
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto construct_at
Definition construct_at.h:27
Definition lazy.h:165
constexpr auto nullopt
Definition nullopt.h:15
Expected(T &&) -> Expected< meta::UnwrapRefDecay< T >, void >
constexpr auto in_place
Definition in_place.h:8
Definition in_place.h:4
Definition unexpect.h:4