plugify 1.2.8
Loading...
Searching...
No Matches
expected.hpp
1#pragma once
2
3#include "plg/config.hpp"
4
5#if __has_include(<expected>)
6#include <expected>
7#if defined(__cpp_lib_expected) && __cpp_lib_expected >= 202202L
8#define PLUGIFY_HAS_STD_EXPECTED 1
9#else
10#define PLUGIFY_HAS_STD_EXPECTED 0
11#endif
12#else
13#define PLUGIFY_HAS_STD_EXPECTED 0
14#endif
15
16#if !PLUGIFY_HAS_STD_EXPECTED
17#include <concepts>
18#include <deque>
19#include <exception>
20#include <functional>
21#include <memory>
22#include <type_traits>
23#include <utility>
24#include <variant>
25
26// from https://github.com/RishabhRD
27namespace plg {
28 template<class E>
29 class unexpected {
30 public:
31 using value_type = E;
32 constexpr unexpected(unexpected const&) = default;
33 constexpr unexpected(unexpected&&) = default;// NOLINT
34 constexpr auto operator=(unexpected const&) -> unexpected& = default;
35 constexpr auto operator=(unexpected&&) -> unexpected& = default;// NOLINT
36 ~unexpected() = default;
37
38 template<class... Args>
39 requires std::constructible_from<E, Args...>
40 constexpr explicit unexpected(std::in_place_t /*unused*/, Args&&... args)
41 : val(std::forward<Args>(args)...) {}
42
43 template<class U, class... Args>
44 requires std::constructible_from<E, std::initializer_list<U>&, Args...>
45 constexpr explicit unexpected(std::in_place_t /*unused*/,
46 std::initializer_list<U> i_list,
47 Args&&... args)
48 : val(i_list, std::forward<Args>(args)...) {}
49
50 template<class Err = E>
51 requires(!std::same_as<std::remove_cvref_t<Err>, unexpected>) &&
52 (!std::same_as<std::remove_cvref_t<Err>, std::in_place_t>) &&
53 std::constructible_from<E, Err>
54 constexpr explicit unexpected(Err&& err)// NOLINT
55 : val(std::forward<Err>(err)) {}
56
57 constexpr auto value() const& noexcept -> E const& { return val; }
58 constexpr auto value() & noexcept -> E& { return val; }
59 constexpr auto value() const&& noexcept -> E const&& {
60 return std::move(val);
61 }
62 constexpr auto value() && noexcept -> E&& { return std::move(val); }
63
64 constexpr void swap(unexpected& other) noexcept(
65 std::is_nothrow_swappable_v<E>)
66 requires(std::is_swappable_v<E>)
67 {
68 using std::swap;
69 swap(val, other.val);
70 }
71
72 template<class E2>
73 requires(requires(E const& x, E2 const& y) {
74 { x == y } -> std::convertible_to<bool>;
75 })
76 friend constexpr auto operator==(unexpected const& x, unexpected<E2> const& y) -> bool {
77 return x.value() == y.value();
78 }
79
80 friend constexpr void swap(unexpected& x, unexpected& y) noexcept(noexcept(x.swap(y)))
81 requires(std::is_swappable_v<E>)
82 {
83 x.swap(y);
84 }
85
86 private:
87 E val;
88 };
89
90 template<class E>
92
93 template<class E>
95
96 template<>
97 class bad_expected_access<void> : public std::exception {
98 protected:
99 bad_expected_access() noexcept = default;
102 auto operator=(bad_expected_access const&) -> bad_expected_access& = default;
103 auto operator=(bad_expected_access&&) -> bad_expected_access& = default;
104 ~bad_expected_access() override = default;
105
106 public:
107 auto what() const noexcept -> char const* override {// NOLINT
108 return "bad expected access";
109 }
110 };
111
112 template<class E>
114 public:
115 explicit bad_expected_access(E e) : val(std::move(e)) {}
116 auto what() const noexcept -> char const* override {// NOLINT
117 return "bad expected access";
118 }
119
120 auto error() & noexcept -> E& { return val; }
121 auto error() const& noexcept -> E const& { return val; }
122 auto error() && noexcept -> E&& { return std::move(val); }
123 auto error() const&& noexcept -> const E&& { return std::move(val); }
124
125 private:
126 E val;
127 };
128
129 struct unexpect_t {};
130 inline constexpr unexpect_t unexpect{};
131
132 namespace detail {
133 template<typename T>
134 concept non_void_destructible = std::same_as<T, void> || std::destructible<T>;
135 }
136
137 template<detail::non_void_destructible T, std::destructible E>
138 class expected;
139
140 namespace detail {
141 template<typename T, typename E, typename U, typename G, typename UF,
142 typename GF>
144 std::constructible_from<T, UF> &&
145 std::constructible_from<E, GF> &&
146 (!std::constructible_from<T, expected<U, G>&>) &&
147 (!std::constructible_from<T, expected<U, G>>) &&
148 (!std::constructible_from<T, expected<U, G> const&>) &&
149 (!std::constructible_from<T, expected<U, G> const>) &&
150 (!std::convertible_to<expected<U, G>&, T>) &&
151 (!std::convertible_to<expected<U, G>&&, T>) &&
152 (!std::convertible_to<expected<U, G> const&, T>) &&
153 (!std::convertible_to<expected<U, G> const&&, T>) &&
154 (!std::constructible_from<unexpected<E>, expected<U, G>&>) &&
155 (!std::constructible_from<unexpected<E>, expected<U, G>>) &&
156 (!std::constructible_from<unexpected<E>, expected<U, G> const&>) &&
157 (!std::constructible_from<unexpected<E>, expected<U, G> const>);
158
159 template<typename T>
161 std::same_as<std::remove_cvref_t<T>, unexpected<typename T::value_type>>;
162
163 template<typename T>
164 concept is_expected =
165 std::same_as<std::remove_cvref_t<T>,
166 expected<typename T::value_type, typename T::error_type>>;
167
168 // This function makes sure expected doesn't get into valueless_by_exception
169 // state due to any exception while assignment
170 template<class T, class U, class... Args>
171 constexpr void reinit_expected(T& newval, U& oldval, Args&&... args) {
172 if constexpr (std::is_nothrow_constructible_v<T, Args...>) {
173 std::destroy_at(std::addressof(oldval));
174 std::construct_at(std::addressof(newval), std::forward<Args>(args)...);
175 } else if constexpr (std::is_nothrow_move_constructible_v<T>) {
176 T tmp(std::forward<Args>(args)...);
177 std::destroy_at(std::addressof(oldval));
178 std::construct_at(std::addressof(newval), std::move(tmp));
179 } else {
180 U tmp(std::move(oldval));
181 std::destroy_at(std::addressof(oldval));
182 try {
183 std::construct_at(std::addressof(newval), std::forward<Args>(args)...);
184 } catch (...) {
185 std::construct_at(std::addressof(oldval), std::move(tmp));
186 throw;
187 }
188 }
189 }
190
191 }// namespace detail
192
193 template<detail::non_void_destructible T, std::destructible E>
194 class expected {
195 public:
196 using value_type = T;
197 using error_type = E;
199
200 template<class U>
202
203 // constructors
204 // postcondition: has_value() = true
205 constexpr expected()
206 requires std::default_initializable<T>
207 : val{} {};
208
209 // postcondition: has_value() = rhs.has_value()
210 constexpr expected(expected const& rhs)
211 requires std::copy_constructible<T> && std::copy_constructible<E> &&
212 std::is_trivially_copy_constructible_v<T> &&
213 std::is_trivially_copy_constructible_v<E>
214 = default;
215
216 // postcondition: has_value() = rhs.has_value()
217 constexpr expected(expected const& rhs)
218 requires std::copy_constructible<T> && std::copy_constructible<E>
219 : has_val(rhs.has_val) {
220 if (rhs.has_value()) {
221 std::construct_at(std::addressof(this->val), *rhs);
222 } else {
223 std::construct_at(std::addressof(this->unex), rhs.error());
224 }
225 }
226
227 constexpr expected(expected&&) noexcept(
228 std::is_nothrow_move_constructible_v<T> &&
229 std::is_nothrow_move_constructible_v<E>)
230 requires std::move_constructible<T> && std::move_constructible<E> &&
231 std::is_trivially_move_constructible_v<T> &&
232 std::is_trivially_move_constructible_v<E>
233 = default;
234
235 constexpr expected(expected&& rhs) noexcept(
236 std::is_nothrow_move_constructible_v<T> &&
237 std::is_nothrow_move_constructible_v<E>)
238 requires std::move_constructible<T> && std::move_constructible<E>
239 : has_val(rhs.has_value()) {
240 if (rhs.has_value()) {
241 std::construct_at(std::addressof(this->val), std::move(*rhs));
242 } else {
243 std::construct_at(std::addressof(this->unex), std::move(rhs.error()));
244 }
245 }
246
247 template<class U, class G>
248 requires detail::expected_constructible_from_other<T, E, U, G, U const&,
249 G const&>
250 constexpr explicit(!std::convertible_to<U const&, T> ||
251 !std::convertible_to<G const&, E>)
252 expected(expected<U, G> const& rhs)// NOLINT
253 : has_val(rhs.has_value()) {
254 using UF = U const&;
255 using GF = G const&;
256 if (rhs.has_value()) {
257 std::construct_at(std::addressof(this->val), std::forward<UF>(*rhs));
258 } else {
259 std::construct_at(std::addressof(this->unex),
260 std::forward<GF>(rhs.error()));
261 }
262 }
263
264 template<class U, class G>
266 constexpr explicit(!std::convertible_to<U, T> || !std::convertible_to<G, E>)
267 expected(expected<U, G>&& rhs)// NOLINT
268 : has_val(rhs.has_value()) {
269 using UF = U const&;
270 using GF = G const&;
271 if (rhs.has_value()) {
272 std::construct_at(std::addressof(this->val), std::forward<UF>(*rhs));
273 } else {
274 std::construct_at(std::addressof(this->unex),
275 std::forward<GF>(rhs.error()));
276 }
277 }
278
279 template<class U = T>
280 requires(!std::same_as<std::remove_cvref_t<U>, std::in_place_t>) &&
281 (!std::same_as<expected<T, E>, std::remove_cvref_t<U>>) &&
283 std::constructible_from<T, U>
284 constexpr explicit(!std::convertible_to<U, T>) expected(U&& v)// NOLINT
285 : val(std::forward<U>(v)) {}
286
287 template<class G>
288 requires std::constructible_from<E, G const&>
289 constexpr explicit(!std::convertible_to<G const&, E>)
290 expected(unexpected<G> const& e)// NOLINT
291 : has_val{false}, unex(std::forward<G const&>(e.value())) {}
292
293 template<class G>
294 requires std::constructible_from<E, G>
295 constexpr explicit(!std::convertible_to<G, E>)
296 expected(unexpected<G>&& e)// NOLINT
297 : has_val{false}, unex(std::forward<G>(e.value())) {}
298
299 template<class... Args>
300 requires std::constructible_from<T, Args...>
301 constexpr explicit expected(std::in_place_t /*unused*/, Args&&... args)
302 : val(std::forward<Args>(args)...) {}
303
304 template<class U, class... Args>
305 requires std::constructible_from<T, std::initializer_list<U>&, Args...>
306 constexpr explicit expected(std::in_place_t /*unused*/,
307 std::initializer_list<U> il,
308 Args&&... args)
309 : val(il, std::forward<Args>(args)...) {}
310
311 template<class... Args>
312 requires std::constructible_from<E, Args...>
313 constexpr explicit expected(unexpect_t /*unused*/, Args&&... args)
314 : has_val{false}, unex(std::forward<Args>(args)...) {}
315
316 template<class U, class... Args>
317 requires std::constructible_from<E, std::initializer_list<U>&,
318 Args...>
319 constexpr explicit expected(unexpect_t /*unused*/,
320 std::initializer_list<U> il,
321 Args&&... args)
322 : has_val(false),
323 unex(il, std::forward<Args>(args)...) {}
324
325 // destructor
326 constexpr ~expected() {
327 if constexpr (std::is_trivially_destructible_v<T> and
328 std::is_trivially_destructible_v<E>) {
329 } else if constexpr (std::is_trivially_destructible_v<T>) {
330 if (!has_val) {
331 std::destroy_at(std::addressof(this->unex));
332 }
333 } else if constexpr (std::is_trivially_destructible_v<E>) {
334 if (has_val) {
335 std::destroy_at(std::addressof(this->val));
336 }
337 } else {
338 if (has_val) {
339 std::destroy_at(std::addressof(this->val));
340 } else {
341 std::destroy_at(std::addressof(this->unex));
342 }
343 }
344 }
345
346 // assignment
347 constexpr auto operator=(expected const& rhs)// NOLINT
348 -> expected&
349 requires std::is_copy_assignable_v<T> &&
350 std::is_copy_constructible_v<T> &&
351 std::is_copy_assignable_v<E> &&
352 std::is_copy_constructible_v<E> &&
353 (std::is_nothrow_move_constructible_v<E> ||
354 std::is_nothrow_move_constructible_v<T>)
355 {
356 if (this->has_value() and rhs.has_value()) {
357 this->val = *rhs;
358 } else if (this->has_value()) {
359 detail::reinit_expected(this->unex, this->val, rhs.error());
360 } else if (rhs.has_value()) {
361 detail::reinit_expected(this->val, this->unex, *rhs);
362 } else {
363 this->unex = rhs.error();
364 }
365 has_val = rhs.has_value();
366 return *this;
367 }
368
369 constexpr auto operator=(expected&& rhs)//
370 noexcept(std::is_nothrow_move_assignable_v<T> &&
371 std::is_nothrow_move_constructible_v<T> &&
372 std::is_nothrow_move_assignable_v<E> &&
373 std::is_nothrow_move_constructible_v<E>)
374 -> expected&
375 requires std::is_move_constructible_v<T> &&
376 std::is_move_assignable_v<T> &&
377 std::is_move_constructible_v<E> &&
378 std::is_move_assignable_v<E> &&
379 (std::is_nothrow_move_constructible_v<T> || std::is_nothrow_move_constructible_v<E>)
380 {
381 if (this->has_value() and rhs.has_value()) {
382 this->val = std::move(*rhs);
383 } else if (this->has_value()) {
384 detail::reinit_expected(this->unex, this->val, std::move(rhs.error()));
385 } else if (rhs.has_value()) {
386 detail::reinit_expected(this->val, this->unex, std::move(*rhs));
387 } else {
388 this->unex = std::move(rhs.error());
389 }
390 has_val = rhs.has_value();
391 return *this;
392 }
393
394 template<class U = T>
395 constexpr auto operator=(U&& rhs) -> expected& requires(!std::same_as<expected, std::remove_cvref_t<U>>) &&
396 (!detail::is_unexpected<std::remove_cvref_t<U>>) &&
397 std::constructible_from<T, U>&& std::is_assignable_v<T&, U> &&
398 (std::is_nothrow_constructible_v<T, U> ||
399 std::is_nothrow_move_constructible_v<T> ||
400 std::is_nothrow_move_constructible_v<E>) {
401 if (this->has_value()) {
402 this->val = std::forward<U>(rhs);
403 return *this;
404 }
405 detail::reinit_expected(this->val, this->unex, std::forward<U>(rhs));
406 has_val = true;
407 return *this;
408 }
409
410 template<class G>
411 requires std::constructible_from<E, G const&> &&
412 std::is_assignable_v<E&, G const&> &&
413 (std::is_nothrow_constructible_v<E, G const&> ||
414 std::is_nothrow_move_constructible_v<T> ||
415 std::is_nothrow_move_constructible_v<E>)
416 constexpr auto operator=(unexpected<G> const& e) -> expected& {
417 using GF = G const&;
418 if (has_value()) {
419 detail::reinit_expected(this->unex, this->val,
420 std::forward<GF>(e.value()));
421 } else {
422 this->unex = std::forward<GF>(e.value());
423 }
424 has_val = false;
425 return *this;
426 }
427
428 template<class G>
429 requires std::constructible_from<E, G> &&
430 std::is_assignable_v<E&, G> &&
431 (std::is_nothrow_constructible_v<E, G> ||
432 std::is_nothrow_move_constructible_v<T> ||
433 std::is_nothrow_move_constructible_v<E>)
434 constexpr auto operator=(unexpected<G>&& e) -> expected& {
435 using GF = G;
436 if (has_value()) {
437 detail::reinit_expected(this->unex, this->val,
438 std::forward<GF>(e.value()));
439 } else {
440 this->unex = std::forward<GF>(e.value());
441 }
442 has_val = false;
443 return *this;
444 }
445
446 // modifiers
447 template<class... Args>
448 requires std::is_nothrow_constructible_v<T, Args...>
449 constexpr auto emplace(Args&&... args) noexcept -> T& {
450 if (has_value()) {
451 std::destroy_at(std::addressof(this->val));
452 } else {
453 std::destroy_at(std::addressof(this->unex));
454 has_val = true;
455 }
456 return *std::construct_at(std::addressof(this->val),
457 std::forward<Args>(args)...);
458 }
459
460 template<class U, class... Args>
461 requires std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>
462 constexpr auto emplace(std::initializer_list<U> il,
463 Args&&... args) noexcept -> T& {
464 if (has_value()) {
465 std::destroy_at(std::addressof(this->val));
466 } else {
467 std::destroy_at(std::addressof(this->unex));
468 has_val = true;
469 }
470 return *std::construct_at(std::addressof(this->val), il,
471 std::forward<Args>(args)...);
472 }
473
474 // swap
475 constexpr void swap(expected& rhs) noexcept(
476 std::is_nothrow_constructible_v<T> &&
477 std::is_nothrow_swappable_v<T> &&
478 std::is_nothrow_move_constructible_v<E> &&
479 std::is_nothrow_swappable_v<E>)
480 requires std::is_swappable_v<T> &&
481 std::is_swappable_v<E> &&
482 std::is_move_constructible_v<T> &&
483 std::is_move_constructible_v<E> &&
484 (std::is_nothrow_constructible_v<T> ||
485 std::is_nothrow_constructible_v<E>)
486 {
487 if (rhs.has_value()) {
488 if (has_value()) {
489 using std::swap;
490 swap(this->val, rhs.val);
491 } else {
492 rhs.swap(*this);
493 }
494 } else {
495 if (has_value()) {
496 if constexpr (std::is_nothrow_move_constructible_v<E>) {
497 E tmp(std::move(rhs.unex));
498 std::destroy_at(std::addressof(rhs.unex));
499 try {
500 std::construct_at(std::addressof(rhs.val), std::move(this->val));
501 std::destroy_at(std::addressof(this->val));
502 std::construct_at(std::addressof(this->unex), std::move(tmp));
503 } catch (...) {
504 std::construct_at(std::addressof(rhs.unex), std::move(tmp));
505 throw;
506 }
507 } else {
508 T tmp(std::move(this->val));
509 std::destroy_at(std::addressof(this->val));
510 try {
511 std::construct_at(std::addressof(this->unex), std::move(rhs.unex));
512 std::destroy_at(std::addressof(rhs.unex));
513 std::construct_at(std::addressof(rhs.val), std::move(tmp));
514 } catch (...) {
515 std::construct_at(std::addressof(this->val), std::move(tmp));
516 throw;
517 }
518 }
519 has_val = false;
520 rhs.has_val = true;
521 } else {
522 using std::swap;
523 swap(this->unex, rhs.unex);
524 }
525 }
526 }
527
528 // observers
529
530 // precondition: has_value() = true
531 constexpr auto operator->() const noexcept -> T const* {
532 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
533 return std::addressof(this->val);
534 }
535
536 // precondition: has_value() = true
537 constexpr auto operator->() noexcept -> T* {
538 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
539 return std::addressof(this->val);
540 }
541
542 // precondition: has_value() = true
543 constexpr auto operator*() const& noexcept -> T const& {
544 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
545 return this->val;
546 }
547
548 // precondition: has_value() = true
549 constexpr auto operator*() & noexcept -> T& {
550 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
551 return this->val;
552 }
553
554 // precondition: has_value() = true
555 constexpr auto operator*() const&& noexcept -> T const&& {
556 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
557 return std::move(this->val);
558 }
559
560 // precondition: has_value() = true
561 constexpr auto operator*() && noexcept -> T&& {
562 PLUGIFY_ASSERT(this->has_val, "requires the expected to contain a value");
563 return std::move(this->val);
564 }
565
566 constexpr explicit operator bool() const noexcept { return has_val; }
567
568 [[nodiscard]] constexpr auto has_value() const noexcept -> bool {
569 return has_val;
570 }
571
572 constexpr auto value() const& -> T const& {
573 if (!has_value()) {
574 PLUGIFY_THROW("bad expected access", bad_expected_access, std::as_const(error()));
575 }
576 return this->val;
577 }
578
579 constexpr auto value() & -> T& {
580 if (!has_value()) {
581 PLUGIFY_THROW("bad expected access", bad_expected_access, std::as_const(error()));
582 }
583 return this->val;
584 }
585
586 constexpr auto value() const&& -> T const&& {
587 if (!has_value()) {
588 PLUGIFY_THROW("bad expected access", bad_expected_access, std::move(error()));
589 }
590 return std::move(this->val);
591 }
592
593 constexpr auto value() && -> T&& {
594 if (!has_value()) {
595 PLUGIFY_THROW("bad expected access", bad_expected_access, std::move(error()));
596 }
597 return std::move(this->val);
598 }
599
600 // precondition: has_value() = false
601 constexpr auto error() const& -> E const& {
602 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
603 return this->unex;
604 }
605
606 // precondition: has_value() = false
607 constexpr auto error() & -> E& {
608 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
609 return this->unex;
610 }
611
612 // precondition: has_value() = false
613 constexpr auto error() const&& -> E const&& {
614 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
615 return std::move(this->unex);
616 }
617
618 // precondition: has_value() = false
619 constexpr auto error() && -> E&& {
620 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
621 return std::move(this->unex);
622 }
623
624 template<class U>
625 requires std::is_copy_constructible_v<T> && std::is_convertible_v<U, T>
626 constexpr auto value_or(U&& v) const& -> T {
627 return has_value() ? **this : static_cast<T>(std::forward<U>(v));
628 }
629
630 template<class U>
631 requires std::is_move_constructible_v<T> && std::is_convertible_v<U, T>
632 constexpr auto value_or(U&& v) && -> T {
633 return has_value() ? std::move(**this) : static_cast<T>(std::forward<U>(v));
634 }
635
636 template<class F, class V = T&,
637 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
638 requires detail::is_expected<U> &&
639 std::is_same_v<typename U::error_type, E> &&
640 std::is_copy_constructible_v<E> && std::is_copy_constructible_v<T>
641 constexpr auto and_then(F&& f) & {
642 if (has_value()) {
643 return std::invoke(std::forward<F>(f), **this);
644 }
645 return U(unexpect, error());
646 }
647
648 template<class F, class V = T const&,
649 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
650 requires detail::is_expected<U> &&
651 std::is_same_v<typename U::error_type, E> &&
652 std::is_copy_constructible_v<E> &&
653 std::is_copy_constructible_v<T>
654 constexpr auto and_then(F&& f) const& {
655 if (has_value()) {
656 return std::invoke(std::forward<F>(f), **this);
657 }
658 return U(unexpect, error());
659 }
660
661 template<class F, class V = T&&,
662 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
663 requires detail::is_expected<U> &&
664 std::is_same_v<typename U::error_type, E> &&
665 std::is_move_constructible_v<E> &&
666 std::is_move_constructible_v<T>
667 constexpr auto and_then(F&& f) && {
668 if (has_value()) {
669 return std::invoke(std::forward<F>(f), std::move(**this));
670 }
671 return U(unexpect, std::move(error()));
672 }
673
674 template<class F, class V = T const&&,
675 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
676 requires detail::is_expected<U> &&
677 std::is_same_v<typename U::error_type, E> &&
678 std::is_move_constructible_v<E> &&
679 std::is_move_constructible_v<T>
680 constexpr auto and_then(F&& f) const&& {
681 if (has_value()) {
682 return std::invoke(std::forward<F>(f), std::move(**this));
683 }
684 return U(unexpect, std::move(error()));
685 }
686
687 template<class F, class V = E&,
688 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
689 requires detail::is_expected<G> &&
690 std::is_same_v<typename G::value_type, T> &&
691 std::is_copy_constructible_v<T> &&
692 std::is_copy_constructible_v<E>
693 constexpr auto or_else(F&& f) & {
694 if (has_value()) {
695 return G(**this);
696 }
697 return std::invoke(std::forward<F>(f), error());
698 }
699
700 template<class F, class V = E const&,
701 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
702 requires detail::is_expected<G> &&
703 std::is_same_v<typename G::value_type, T> &&
704 std::is_copy_constructible_v<T> &&
705 std::is_copy_constructible_v<E>
706 constexpr auto or_else(F&& f) const& {
707 if (has_value()) {
708 return G(**this);
709 }
710 return std::invoke(std::forward<F>(f), error());
711 }
712
713 template<class F, class V = E&&,
714 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
715 requires detail::is_expected<G> &&
716 std::is_same_v<typename G::value_type, T> &&
717 std::is_move_constructible_v<T> &&
718 std::is_move_constructible_v<E>
719 constexpr auto or_else(F&& f) && {
720 if (has_value()) {
721 return G(std::move(**this));
722 }
723 return std::invoke(std::forward<F>(f), std::move(error()));
724 }
725
726 template<class F, class V = E const&&,
727 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
728 requires detail::is_expected<G> &&
729 std::is_same_v<typename G::value_type, T> &&
730 std::is_move_constructible_v<T> &&
731 std::is_move_constructible_v<E>
732 constexpr auto or_else(F&& f) const&& {
733 if (has_value()) {
734 return G(std::move(**this));
735 }
736 return std::invoke(std::forward<F>(f), std::move(error()));
737 }
738
739 template<class F, class V = E&,
740 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
741 requires std::is_void_v<G> &&
742 std::is_copy_constructible_v<T> &&
743 std::is_copy_constructible_v<E>
744 constexpr auto or_else(F&& f) & {
745 if (has_value()) {
746 return expected(*this);
747 }
748 std::invoke(std::forward<F>(f), error());
749 return expected(*this);
750 }
751
752 template<class F, class V = E const&,
753 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
754 requires std::is_void_v<G> &&
755 std::is_copy_constructible_v<T> &&
756 std::is_copy_constructible_v<E>
757 constexpr auto or_else(F&& f) const& {
758 if (has_value()) {
759 return expected(*this);
760 }
761 std::invoke(std::forward<F>(f), error());
762 return expected(*this);
763 }
764
765 template<class F, class V = E&&,
766 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
767 requires std::is_void_v<G> &&
768 std::is_move_constructible_v<T> &&
769 std::is_move_constructible_v<E> &&
770 std::is_copy_constructible_v<E>
771 constexpr auto or_else(F&& f) && {
772 if (has_value()) {
773 return expected(std::move(*this));
774 }
775 // TODO: is this copy necessary, as f can be just read argument function
776 std::invoke(std::forward<F>(f), error());
777 return expected(std::move(*this));
778 }
779
780 template<class F, class V = E const&&,
781 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
782 requires std::is_void_v<G> &&
783 std::is_move_constructible_v<T> &&
784 std::is_move_constructible_v<E> &&
785 std::is_copy_constructible_v<E>
786 constexpr auto or_else(F&& f) const&& {
787 if (!has_value()) {
788 return expected(std::move(*this));
789 }
790 // TODO: is this copy necessary, as f can be just read argument function
791 std::invoke(std::forward<F>(f), error());
792 return expected(std::move(*this));
793 }
794
795 template<class F, class V = T&,
796 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
797 requires std::is_copy_constructible_v<E> &&
798 std::is_copy_constructible_v<T>
799 constexpr auto transform(F&& f) & {
800 if (has_value()) {
801 if constexpr (!std::same_as<U, void>) {
802 return expected<U, E>(std::invoke(std::forward<F>(f), **this));
803 } else {
804 std::invoke(std::forward<F>(f), std::move(**this));
805 return expected<U, E>();
806 }
807 }
808 return expected<U, E>(unexpect, error());
809 }
810
811 template<class F, class V = T const&,
812 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
813 requires std::is_copy_constructible_v<E> &&
814 std::is_copy_constructible_v<T>
815 constexpr auto transform(F&& f) const& {
816 if (has_value()) {
817 if constexpr (!std::same_as<U, void>) {
818 return expected<U, E>(std::invoke(std::forward<F>(f), **this));
819 } else {
820 std::invoke(std::forward<F>(f), std::move(**this));
821 return expected<U, E>();
822 }
823 }
824 return expected<U, E>(unexpect, error());
825 }
826
827 template<class F, class V = T&&,
828 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
829 requires std::is_move_constructible_v<E> &&
830 std::is_move_constructible_v<T>
831 constexpr auto transform(F&& f) && {
832 if (has_value()) {
833 if constexpr (!std::same_as<U, void>) {
834 return expected<U, E>(
835 std::invoke(std::forward<F>(f), std::move(**this)));
836 } else {
837 std::invoke(std::forward<F>(f), std::move(**this));
838 return expected<U, E>();
839 }
840 }
841 return expected<U, E>(unexpect, std::move(error()));
842 }
843
844 template<class F, class V = T const&&,
845 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
846 requires std::is_move_constructible_v<E> &&
847 std::is_move_constructible_v<T>
848 constexpr auto transform(F&& f) const&& {
849 if (has_value()) {
850 if constexpr (!std::same_as<U, void>) {
851 return expected<U, E>(
852 std::invoke(std::forward<F>(f), std::move(**this)));
853 } else {
854 std::invoke(std::forward<F>(f), std::move(**this));
855 return expected<U, E>();
856 }
857 }
858 return expected<U, E>(unexpect, std::move(error()));
859 }
860
861 template<class F, class V = E&,
862 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
863 requires std::is_copy_constructible_v<T> &&
864 std::is_copy_constructible_v<E>
865 constexpr auto transform_error(F&& f) & {
866 if (has_value()) {
867 return expected<T, G>(**this);
868 }
869 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
870 }
871
872 template<class F, class V = E const&,
873 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
874 requires std::is_copy_constructible_v<T> &&
875 std::is_copy_constructible_v<E>
876 constexpr auto transform_error(F&& f) const& {
877 if (has_value()) {
878 return expected<T, G>(**this);
879 }
880 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
881 }
882
883 template<class F, class V = E&&,
884 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
885 requires std::is_move_constructible_v<T> &&
886 std::is_move_constructible_v<E>
887 constexpr auto transform_error(F&& f) && {
888 if (has_value()) {
889 return expected<T, G>(std::move(**this));
890 }
891 return expected<T, G>(unexpect,
892 std::invoke(std::forward<F>(f), std::move(error())));
893 }
894
895 template<class F, class V = E const&&,
896 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
897 requires std::is_move_constructible_v<T> &&
898 std::is_move_constructible_v<E>
899 constexpr auto transform_error(F&& f) const&& {
900 if (has_value()) {
901 return expected<T, G>(std::move(**this));
902 }
903 return expected<T, G>(unexpect,
904 std::invoke(std::forward<F>(f), std::move(error())));
905 }
906
907 // equality operators
908 template<class T2, class E2>
909 requires(!std::is_void_v<T2>) &&
910 requires(T const& t1, T2 const& t2, E const& e1, E2 const& e2) {
911 { t1 == t2 } -> std::convertible_to<bool>;
912 { e1 == e2 } -> std::convertible_to<bool>;
913 }
914 friend constexpr auto operator==(expected const& x, expected<T2, E2> const& y)
915 -> bool {
916 if (x.has_value() != y.has_value()) {
917 return false;
918 }
919 return x.has_value() ? (*x == *y) : (x.error() == y.error());
920 }
921
922 template<class T2>
923 requires(!detail::is_expected<T2>) && requires(T const& x, T2 const& v) {
924 { x == v } -> std::convertible_to<bool>;
925 }
926 friend constexpr auto operator==(expected const& x, T2 const& v) -> bool {
927 return x.has_value() && static_cast<bool>(*x == v);
928 }
929
930 template<class E2>
931 requires requires(E const& x, unexpected<E2> const& e) {
932 { x == e.value() } -> std::convertible_to<bool>;
933 }
934 friend constexpr auto operator==(expected const& x, unexpected<E2> const& e)
935 -> bool {
936 return !x.has_value() && static_cast<bool>(x.error() == e.value());
937 }
938
939 // specialized algorithms
940 friend constexpr void swap(expected& x,
941 expected& y) noexcept(noexcept(x.swap(y))) {
942 x.swap(y);
943 }
944
945 private:
946 bool has_val{true};
947 union {
948 T val;
949 E unex;
950 };
951 };
952
953 template<std::destructible E>
954 class expected<void, E> {
955 public:
956 using value_type = void;
957 using error_type = E;
959
960 template<class U>
962
963 // constructors
964
965 // postcondition: has_value() = true
966 constexpr expected() noexcept {}// NOLINT
967
968 constexpr expected(
969 expected const& rhs)
970 requires std::is_copy_constructible_v<E> &&
971 std::is_trivially_copy_constructible_v<E>
972 = default;
973
974 constexpr expected(
975 expected const& rhs)
976 requires std::is_copy_constructible_v<E>
977 : has_val(rhs.has_value()) {
978 if (!rhs.has_value()) {
979 std::construct_at(std::addressof(this->unex), rhs.error());
980 }
981 }
982
983 constexpr expected(expected&&) noexcept(std::is_nothrow_move_constructible_v<E>)
984 requires std::is_move_constructible_v<E> &&
985 std::is_trivially_move_constructible_v<E>
986 = default;
987
988 constexpr expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<E>)
989 requires std::is_move_constructible_v<E>
990 : has_val(rhs.has_value()) {
991 if (!rhs.has_value()) {
992 std::construct_at(std::addressof(this->unex), std::move(rhs.error()));
993 }
994 }
995
996 template<class U, class G>
997 requires std::is_void_v<U> && std::is_constructible_v<E, G const&> && (!std::is_constructible_v<unexpected<E>, expected<U, G>&>) && (!std::is_constructible_v<unexpected<E>, expected<U, G>>) && (!std::is_constructible_v<unexpected<E>, expected<U, G> const&>) && (!std::is_constructible_v<unexpected<E>, expected<U, G> const&>)
998 constexpr explicit(!std::is_convertible_v<G const&, E>)
999 expected(expected<U, G> const& rhs)// NOLINT
1000 : has_val(rhs.has_value()) {
1001 if (!rhs.has_value()) {
1002 std::construct_at(std::addressof(this->unex),
1003 std::forward<G const&>(rhs.error()));
1004 }
1005 }
1006
1007 template<class U, class G>
1008 requires std::is_void_v<U> && std::is_constructible_v<E, G> && (!std::is_constructible_v<unexpected<E>, expected<U, G>&>) && (!std::is_constructible_v<unexpected<E>, expected<U, G>>) && (!std::is_constructible_v<unexpected<E>, expected<U, G> const&>) && (!std::is_constructible_v<unexpected<E>, expected<U, G> const&>)
1009 constexpr explicit(!std::is_convertible_v<G const&, E>)
1010 expected(expected<U, G>&& rhs)// NOLINT
1011 : has_val(rhs.has_value()) {
1012 if (!rhs.has_value()) {
1013 std::construct_at(std::addressof(this->unex),
1014 std::forward<G>(rhs.error()));
1015 }
1016 }
1017
1018 template<class G>
1019 requires std::is_constructible_v<E, G const&>
1020 constexpr explicit(!std::is_convertible_v<G const&, E>)
1021 expected(unexpected<G> const& e)// NOLINT
1022 : has_val(false), unex(std::forward<G const&>(e.value())) {}
1023
1024 template<class G>
1025 requires std::is_constructible_v<E, G>
1026 constexpr explicit(!std::is_convertible_v<G, E>)
1027 expected(unexpected<G>&& e)// NOLINT
1028 : has_val(false), unex(std::forward<G>(e.value())) {}
1029
1030 constexpr explicit expected(std::in_place_t /*unused*/) noexcept {}
1031
1032 template<class... Args>
1033 requires std::is_constructible_v<E, Args...>
1034 constexpr explicit expected(unexpect_t /*unused*/, Args&&... args)
1035 : has_val(false), unex(std::forward<Args>(args)...) {}
1036
1037 template<class U, class... Args>
1038 requires std::is_constructible_v<E, std::initializer_list<U>&, Args...>
1039 constexpr explicit expected(unexpect_t /*unused*/, std::initializer_list<U> il, Args... args)
1040 : has_val(false),
1041 unex(il, std::forward<Args>(args)...) {}
1042
1043 // destructor
1044 constexpr ~expected() {
1045 if constexpr (std::is_trivially_destructible_v<E>) {
1046 } else {
1047 if (!has_value()) std::destroy_at(std::addressof(this->unex));
1048 }
1049 }
1050
1051 // assignment
1052 constexpr auto operator=(expected const& rhs) -> expected&// NOLINT
1053 requires std::is_copy_assignable_v<E> &&
1054 std::is_copy_constructible_v<E>
1055 {
1056 if (has_value() && rhs.has_value()) {
1057 } else if (has_value()) {
1058 std::construct_at(std::addressof(this->unex), rhs.unex);
1059 has_val = false;
1060 } else if (rhs.has_value()) {
1061 std::destroy_at(std::addressof(this->unex));
1062 has_val = true;
1063 } else {
1064 this->unex = rhs.error();
1065 }
1066 return *this;
1067 }
1068
1069 constexpr auto operator=(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<E> &&
1070 std::is_nothrow_move_assignable_v<E>) -> expected&
1071 requires std::is_move_constructible_v<E> &&
1072 std::is_move_assignable_v<E>
1073 {
1074 if (has_value() && rhs.has_value()) {
1075 } else if (has_value()) {
1076 std::construct_at(std::addressof(this->unex), std::move(rhs.unex));
1077 has_val = false;
1078 } else if (rhs.has_value()) {
1079 std::destroy_at(std::addressof(this->unex));
1080 has_val = true;
1081 } else {
1082 this->unex = std::move(rhs.error());
1083 }
1084 return *this;
1085 }
1086
1087 template<class G>
1088 requires std::is_constructible_v<E, G const&> and
1089 std::is_assignable_v<E&, G const&>
1090 constexpr auto operator=(unexpected<G> const& e) -> expected& {
1091 if (has_value()) {
1092 std::construct_at(std::addressof(this->unex),
1093 std::forward<G const&>(e.value()));
1094 has_val = false;
1095 } else {
1096 this->unex = std::forward<G const&>(e.value());
1097 }
1098 return *this;
1099 }
1100
1101 template<class G>
1102 requires std::is_constructible_v<E, G> &&
1103 std::is_assignable_v<E&, G>
1104 constexpr auto operator=(unexpected<G>&& e) -> expected& {
1105 if (has_value()) {
1106 std::construct_at(std::addressof(this->unex), std::forward<G>(e.value()));
1107 has_val = false;
1108 } else {
1109 this->unex = std::forward<G>(e.value());
1110 }
1111 return *this;
1112 }
1113
1114 // modifiers
1115 constexpr void emplace() noexcept {
1116 if (!has_value()) {
1117 std::destroy_at(std::addressof(this->unex));
1118 has_val = true;
1119 }
1120 }
1121
1122 // swap
1123 constexpr void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<E> &&
1124 std::is_nothrow_swappable_v<E>)
1125 requires std::is_swappable_v<E> &&
1126 std::is_move_constructible_v<E>
1127 {
1128 if (rhs.has_value()) {
1129 if (has_value()) {
1130 } else {
1131 rhs.swap(*this);
1132 }
1133 } else {
1134 if (has_value()) {
1135 std::construct_at(std::addressof(this->unex), std::move(rhs.unex));
1136 std::destroy_at(std::addressof(rhs.unex));
1137 has_val = false;
1138 rhs.has_val = true;
1139 } else {
1140 using std::swap;
1141 swap(this->unex, rhs.unex);
1142 }
1143 }
1144 }
1145
1146 // observers
1147 constexpr explicit operator bool() const noexcept { return has_val; }
1148
1149 [[nodiscard]] constexpr auto has_value() const noexcept -> bool {
1150 return has_val;
1151 }
1152
1153 // precondition: has_value() = true
1154 constexpr void operator*() const noexcept {}
1155
1156 constexpr void value() const& {
1157 if (!has_value()) {
1158 PLUGIFY_THROW("bad expected access", bad_expected_access, std::as_const(error()));
1159 }
1160 }
1161
1162 constexpr void value() && {
1163 if (!has_value()) {
1164 PLUGIFY_THROW("bad expected access", bad_expected_access, std::move(error()));
1165 }
1166 }
1167
1168 // precondition: has_value() = false
1169 constexpr auto error() const& -> E const& {
1170 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
1171 return this->unex;
1172 }
1173
1174 // precondition: has_value() = false
1175 constexpr auto error() & -> E& {
1176 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
1177 return this->unex;
1178 }
1179
1180 // precondition: has_value() = false
1181 constexpr auto error() const&& -> E const&& {
1182 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
1183 return std::move(this->unex);
1184 }
1185
1186 // precondition: has_value() = false
1187 constexpr auto error() && -> E&& {
1188 PLUGIFY_ASSERT(!this->has_val, "requires the expected to contain an error");
1189 return std::move(this->unex);
1190 }
1191
1192 // monadic
1193 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1194 requires detail::is_expected<U> &&
1195 std::is_same_v<typename U::error_type, E> &&
1196 std::is_copy_constructible_v<E>
1197 constexpr auto and_then(F&& f) & {
1198 if (has_value()) {
1199 return std::invoke(std::forward<F>(f));
1200 }
1201 return U(unexpect, error());
1202 }
1203
1204 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1205 requires detail::is_expected<U> &&
1206 std::is_same_v<typename U::error_type, E> &&
1207 std::is_copy_constructible_v<E>
1208 constexpr auto and_then(F&& f) const& {
1209 if (has_value()) {
1210 return std::invoke(std::forward<F>(f));
1211 }
1212 return U(unexpect, error());
1213 }
1214
1215 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1216 requires detail::is_expected<U> &&
1217 std::is_same_v<typename U::error_type, E> &&
1218 std::is_move_constructible_v<E>
1219 constexpr auto and_then(F&& f) && {
1220 if (has_value()) {
1221 return std::invoke(std::forward<F>(f));
1222 }
1223 return U(unexpect, std::move(error()));
1224 }
1225
1226 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1227 requires detail::is_expected<U> &&
1228 std::is_same_v<typename U::error_type, E> &&
1229 std::is_move_constructible_v<E>
1230 constexpr auto and_then(F&& f) const&& {
1231 if (has_value()) {
1232 return std::invoke(std::forward<F>(f));
1233 }
1234 return U(unexpect, std::move(error()));
1235 }
1236
1237 template<class F, class V = E&,
1238 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1239 requires detail::is_expected<G> &&
1240 std::is_same_v<typename G::value_type, void> &&
1241 std::is_copy_constructible_v<E>
1242 constexpr auto or_else(F&& f) & {
1243 if (has_value()) {
1244 return G{};
1245 }
1246 return std::invoke(std::forward<F>(f), error());
1247 }
1248
1249 template<class F, class V = E const&,
1250 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1251 requires detail::is_expected<G> &&
1252 std::is_same_v<typename G::value_type, void> &&
1253 std::is_copy_constructible_v<E>
1254 constexpr auto or_else(F&& f) const& {
1255 if (has_value()) {
1256 return G{};
1257 }
1258 return std::invoke(std::forward<F>(f), error());
1259 }
1260
1261 template<class F, class V = E&&,
1262 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1263 requires detail::is_expected<G> &&
1264 std::is_same_v<typename G::value_type, void> &&
1265 std::is_move_constructible_v<E>
1266 constexpr auto or_else(F&& f) && {
1267 if (has_value()) {
1268 return G{};
1269 }
1270 return std::invoke(std::forward<F>(f), std::move(error()));
1271 }
1272
1273 template<class F, class V = E const&&,
1274 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1275 requires detail::is_expected<G> &&
1276 std::is_same_v<typename G::value_type, void> &&
1277 std::is_move_constructible_v<E>
1278 constexpr auto or_else(F&& f) const&& {
1279 if (has_value()) {
1280 return G{};
1281 }
1282 return std::invoke(std::forward<F>(f), std::move(error()));
1283 }
1284
1285 template<class F, class V = E&,
1286 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1287 requires std::is_void_v<G> &&
1288 std::is_copy_constructible_v<E>
1289 constexpr auto or_else(F&& f) & {
1290 if (has_value()) {
1291 return expected(*this);
1292 }
1293 std::invoke(std::forward<F>(f), error());
1294 return expected(*this);
1295 }
1296
1297 template<class F, class V = E const&,
1298 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1299 requires std::is_void_v<G> &&
1300 std::is_copy_constructible_v<E>
1301 constexpr auto or_else(F&& f) const& {
1302 if (has_value()) {
1303 return expected(*this);
1304 }
1305 std::invoke(std::forward<F>(f), error());
1306 return expected(*this);
1307 }
1308
1309 template<class F, class V = E&&,
1310 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1311 requires std::is_void_v<G> &&
1312 std::is_move_constructible_v<E> &&
1313 std::is_copy_constructible_v<E>
1314 constexpr auto or_else(F&& f) && {
1315 if (has_value()) {
1316 return expected(std::move(*this));
1317 }
1318 // TODO: is this copy necessary, as f can be just read argument function
1319 std::invoke(std::forward<F>(f), error());
1320 return expected(std::move(*this));
1321 }
1322
1323 template<class F, class V = E const&&,
1324 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1325 requires std::is_void_v<G> &&
1326 std::is_move_constructible_v<E> &&
1327 std::is_copy_constructible_v<E>
1328 constexpr auto or_else(F&& f) const&& {
1329 if (!has_value()) {
1330 return expected(std::move(*this));
1331 }
1332 // TODO: is this copy necessary, as f can be just read argument function
1333 std::invoke(std::forward<F>(f), error());
1334 return expected(std::move(*this));
1335 }
1336
1337 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1338 requires std::is_copy_constructible_v<E>
1339 constexpr auto transform(F&& f) & {
1340 if (has_value()) {
1341 if constexpr (!std::same_as<U, void>) {
1342 return expected<U, E>(std::invoke(std::forward<F>(f)));
1343 } else {
1344 std::invoke(std::forward<F>(f));
1345 return expected<U, E>();
1346 }
1347 }
1348 return expected<U, E>(unexpect, error());
1349 }
1350
1351 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1352 requires std::is_copy_constructible_v<E>
1353 constexpr auto transform(F&& f) const& {
1354 if (has_value()) {
1355 if constexpr (!std::same_as<U, void>) {
1356 return expected<U, E>(std::invoke(std::forward<F>(f)));
1357 } else {
1358 std::invoke(std::forward<F>(f));
1359 return expected<U, E>();
1360 }
1361 }
1362 return expected<U, E>(unexpect, error());
1363 }
1364
1365 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1366 requires std::is_move_constructible_v<E>
1367 constexpr auto transform(F&& f) && {
1368 if (has_value()) {
1369 if constexpr (!std::same_as<U, void>) {
1370 return expected<U, E>(std::invoke(std::forward<F>(f)));
1371 } else {
1372 std::invoke(std::forward<F>(f));
1373 return expected<U, E>();
1374 }
1375 }
1376 return expected<U, E>(unexpect, std::move(error()));
1377 }
1378
1379 template<class F, class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1380 requires std::is_move_constructible_v<E>
1381 constexpr auto transform(F&& f) const&& {
1382 if (has_value()) {
1383 if constexpr (!std::same_as<U, void>) {
1384 return expected<U, E>(std::invoke(std::forward<F>(f)));
1385 } else {
1386 std::invoke(std::forward<F>(f));
1387 return expected<U, E>();
1388 }
1389 }
1390 return expected<U, E>(unexpect, std::move(error()));
1391 }
1392
1393 template<class F, class V = E&,
1394 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1395 requires std::is_copy_constructible_v<E>
1396 constexpr auto transform_error(F&& f) & {
1397 if (has_value()) {
1398 return expected<void, G>{};
1399 }
1400 return expected<void, G>(unexpect,
1401 std::invoke(std::forward<F>(f), error()));
1402 }
1403
1404 template<class F, class V = E const&,
1405 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1406 requires std::is_copy_constructible_v<E>
1407 constexpr auto transform_error(F&& f) const& {
1408 if (has_value()) {
1409 return expected<void, G>{};
1410 }
1411 return expected<void, G>(unexpect,
1412 std::invoke(std::forward<F>(f), error()));
1413 }
1414
1415 template<class F, class V = E&&,
1416 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1417 requires std::is_move_constructible_v<E>
1418 constexpr auto transform_error(F&& f) && {
1419 if (has_value()) {
1420 return expected<void, G>{};
1421 }
1422 return expected<void, G>(
1423 unexpect, std::invoke(std::forward<F>(f), std::move(error())));
1424 }
1425
1426 template<class F, class V = E const&&,
1427 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1428 requires std::is_move_constructible_v<E>
1429 constexpr auto transform_error(F&& f) const&& {
1430 if (has_value()) {
1431 return expected<void, G>{};
1432 }
1433 return expected<void, G>(
1434 unexpect, std::invoke(std::forward<F>(f), std::move(error())));
1435 }
1436
1437 // expected equality operators
1438 template<class T2, class E2>
1439 requires std::is_void_v<T2> && requires(E e, E2 e2) {
1440 { e == e2 } -> std::convertible_to<bool>;
1441 }
1442 friend constexpr auto operator==(expected const& x, expected<T2, E2> const& y)
1443 -> bool {
1444 if (x.has_value() != y.has_value()) return false;
1445 return x.has_value() or static_cast<bool>(x.error() == y.error());
1446 }
1447
1448 template<class E2>
1449 requires requires(expected const& x, unexpected<E2> const& e) {
1450 { x.error() == e.value() } -> std::convertible_to<bool>;
1451 }
1452 friend constexpr auto operator==(expected const& x, unexpected<E2> const& e)
1453 -> bool {
1454 return !x.has_value() && static_cast<bool>(x.error() == e.value());
1455 }
1456
1457 // specialized algorithms
1458 friend constexpr void swap(expected& x,
1459 expected& y) noexcept(noexcept(x.swap(y))) {
1460 x.swap(y);
1461 }
1462
1463 private:
1464 bool has_val{true};
1465 union {
1466 E unex;
1467 };
1468 };
1469
1470} // namespace plg
1471
1472namespace std {
1473 template<class U, class G>
1474 using expected = plg::expected<U, G>;
1475
1476 template <class T>
1477 concept is_expected = std::same_as<std::remove_cvref_t<T>, expected<typename T::value_type, typename T::error_type> >;
1478
1479#if PLUGIFY_COMPILER_CLANG
1480 template <class U>
1481 struct unexpected : public plg::unexpected<U> {
1482 using plg::unexpected<U>::unexpected;
1483 };
1484 template <class U>
1486#else
1487 template <class U>
1489#endif
1490
1491} // namespace std
1492
1493#endif // !PLUGIFY_HAS_STD_EXPECTED