196 using value_type = T;
197 using error_type = E;
206 requires std::default_initializable<T>
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>
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);
223 std::construct_at(std::addressof(this->unex), rhs.error());
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>
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));
243 std::construct_at(std::addressof(this->unex), std::move(rhs.error()));
247 template<
class U,
class G>
250 constexpr explicit(!std::convertible_to<U const&, T> ||
251 !std::convertible_to<G const&, E>)
253 : has_val(rhs.has_value()) {
256 if (rhs.has_value()) {
257 std::construct_at(std::addressof(this->val), std::forward<UF>(*rhs));
259 std::construct_at(std::addressof(this->unex),
260 std::forward<GF>(rhs.error()));
264 template<
class U,
class G>
266 constexpr explicit(!std::convertible_to<U, T> || !std::convertible_to<G, E>)
268 : has_val(rhs.has_value()) {
271 if (rhs.has_value()) {
272 std::construct_at(std::addressof(this->val), std::forward<UF>(*rhs));
274 std::construct_at(std::addressof(this->unex),
275 std::forward<GF>(rhs.error()));
279 template<
class U = T>
280 requires(!std::same_as<std::remove_cvref_t<U>, std::in_place_t>) &&
283 std::constructible_from<T, U>
284 constexpr explicit(!std::convertible_to<U, T>)
expected(
U&& v)
285 : val(std::forward<U>(v)) {}
288 requires std::constructible_from<E, G const&>
289 constexpr explicit(!std::convertible_to<G const&, E>)
291 : has_val{
false}, unex(std::forward<G const&>(
e.value())) {}
294 requires std::constructible_from<E, G>
295 constexpr explicit(!std::convertible_to<G, E>)
297 : has_val{
false}, unex(std::forward<G>(
e.value())) {}
299 template<
class...
Args>
300 requires std::constructible_from<T,
Args...>
302 : val(std::forward<Args>(
args)...) {}
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 ,
307 std::initializer_list<U>
il,
309 : val(
il, std::forward<Args>(
args)...) {}
311 template<
class...
Args>
312 requires std::constructible_from<E,
Args...>
314 : has_val{
false}, unex(std::forward<Args>(
args)...) {}
316 template<
class U,
class...
Args>
317 requires std::constructible_from<E, std::initializer_list<U>&,
320 std::initializer_list<U>
il,
323 unex(
il, std::forward<Args>(
args)...) {}
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>) {
331 std::destroy_at(std::addressof(this->unex));
333 }
else if constexpr (std::is_trivially_destructible_v<E>) {
335 std::destroy_at(std::addressof(this->val));
339 std::destroy_at(std::addressof(this->val));
341 std::destroy_at(std::addressof(this->unex));
347 constexpr auto operator=(
expected const& rhs)
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>)
356 if (this->has_value()
and rhs.has_value()) {
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);
363 this->unex = rhs.error();
365 has_val = rhs.has_value();
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>)
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>)
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));
388 this->unex = std::move(rhs.error());
390 has_val = rhs.has_value();
394 template<
class U = T>
395 constexpr auto operator=(
U&& rhs) ->
expected&
requires(!std::same_as<expected, 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);
405 detail::reinit_expected(this->val, this->unex, std::forward<U>(rhs));
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>)
419 detail::reinit_expected(this->unex, this->val,
420 std::forward<GF>(
e.value()));
422 this->unex = std::forward<GF>(
e.value());
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>)
437 detail::reinit_expected(this->unex, this->val,
438 std::forward<GF>(
e.value()));
440 this->unex = std::forward<GF>(
e.value());
447 template<
class...
Args>
448 requires std::is_nothrow_constructible_v<T,
Args...>
449 constexpr auto emplace(
Args&&...
args)
noexcept -> T& {
451 std::destroy_at(std::addressof(this->val));
453 std::destroy_at(std::addressof(this->unex));
456 return *std::construct_at(std::addressof(this->val),
457 std::forward<Args>(
args)...);
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,
465 std::destroy_at(std::addressof(this->val));
467 std::destroy_at(std::addressof(this->unex));
470 return *std::construct_at(std::addressof(this->val),
il,
471 std::forward<Args>(
args)...);
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>)
487 if (rhs.has_value()) {
490 swap(this->val, rhs.val);
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));
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));
504 std::construct_at(std::addressof(rhs.unex), std::move(
tmp));
508 T
tmp(std::move(this->val));
509 std::destroy_at(std::addressof(this->val));
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));
515 std::construct_at(std::addressof(this->val), std::move(
tmp));
523 swap(this->unex, rhs.unex);
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);
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);
543 constexpr auto operator*()
const&
noexcept -> T
const& {
544 PLUGIFY_ASSERT(this->has_val,
"requires the expected to contain a value");
549 constexpr auto operator*() &
noexcept -> T& {
550 PLUGIFY_ASSERT(this->has_val,
"requires the expected to contain a value");
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);
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);
566 constexpr explicit operator bool()
const noexcept {
return has_val; }
568 [[
nodiscard]]
constexpr auto has_value()
const noexcept ->
bool {
572 constexpr auto value()
const& -> T
const& {
579 constexpr auto value() & -> T& {
586 constexpr auto value()
const&& -> T
const&& {
590 return std::move(this->val);
593 constexpr auto value() && -> T&& {
597 return std::move(this->val);
601 constexpr auto error()
const& -> E
const& {
602 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
607 constexpr auto error() & -> E& {
608 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
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);
619 constexpr auto error() && -> E&& {
620 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
621 return std::move(this->unex);
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));
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));
636 template<
class F,
class V = T&,
637 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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) & {
643 return std::invoke(std::forward<F>(f), **
this);
645 return U(unexpect, error());
648 template<
class F,
class V = T
const&,
649 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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& {
656 return std::invoke(std::forward<F>(f), **
this);
658 return U(unexpect, error());
661 template<
class F,
class V = T&&,
662 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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) && {
669 return std::invoke(std::forward<F>(f), std::move(**
this));
671 return U(unexpect, std::move(error()));
674 template<
class F,
class V = T
const&&,
675 class U = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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&& {
682 return std::invoke(std::forward<F>(f), std::move(**
this));
684 return U(unexpect, std::move(error()));
687 template<
class F,
class V = E&,
688 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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) & {
697 return std::invoke(std::forward<F>(f), error());
700 template<
class F,
class V = E
const&,
701 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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& {
710 return std::invoke(std::forward<F>(f), error());
713 template<
class F,
class V = E&&,
714 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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) && {
721 return G(std::move(**
this));
723 return std::invoke(std::forward<F>(f), std::move(error()));
726 template<
class F,
class V = E
const&&,
727 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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&& {
734 return G(std::move(**
this));
736 return std::invoke(std::forward<F>(f), std::move(error()));
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) & {
748 std::invoke(std::forward<F>(f), error());
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& {
761 std::invoke(std::forward<F>(f), error());
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) && {
776 std::invoke(std::forward<F>(f), error());
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&& {
791 std::invoke(std::forward<F>(f), error());
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) & {
801 if constexpr (!std::same_as<U, void>) {
804 std::invoke(std::forward<F>(f), std::move(**
this));
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& {
817 if constexpr (!std::same_as<U, void>) {
820 std::invoke(std::forward<F>(f), std::move(**
this));
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) && {
833 if constexpr (!std::same_as<U, void>) {
835 std::invoke(std::forward<F>(f), std::move(**
this)));
837 std::invoke(std::forward<F>(f), std::move(**
this));
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&& {
850 if constexpr (!std::same_as<U, void>) {
852 std::invoke(std::forward<F>(f), std::move(**
this)));
854 std::invoke(std::forward<F>(f), std::move(**
this));
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) & {
869 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
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& {
880 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), error()));
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) && {
892 std::invoke(std::forward<F>(f), std::move(error())));
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&& {
904 std::invoke(std::forward<F>(f), std::move(error())));
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>;
916 if (x.has_value() != y.has_value()) {
919 return x.has_value() ? (*x == *y) : (x.error() == y.error());
924 { x == v } -> std::convertible_to<bool>;
926 friend constexpr auto operator==(
expected const& x,
T2 const& v) ->
bool {
927 return x.has_value() &&
static_cast<bool>(*x == v);
932 { x ==
e.value() } -> std::convertible_to<bool>;
936 return !x.has_value() &&
static_cast<bool>(x.error() ==
e.value());
940 friend constexpr void swap(
expected& x,
941 expected& y)
noexcept(
noexcept(x.swap(y))) {
957 using error_type = E;
970 requires std::is_copy_constructible_v<E> &&
971 std::is_trivially_copy_constructible_v<E>
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());
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>
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()));
996 template<
class U,
class G>
998 constexpr explicit(!std::is_convertible_v<G const&, E>)
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()));
1007 template<
class U,
class G>
1009 constexpr explicit(!std::is_convertible_v<G const&, E>)
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()));
1019 requires std::is_constructible_v<E, G const&>
1020 constexpr explicit(!std::is_convertible_v<G const&, E>)
1022 : has_val(
false), unex(std::forward<G const&>(
e.value())) {}
1025 requires std::is_constructible_v<E, G>
1026 constexpr explicit(!std::is_convertible_v<G, E>)
1028 : has_val(
false), unex(std::forward<G>(
e.value())) {}
1030 constexpr explicit expected(std::in_place_t )
noexcept {}
1032 template<
class...
Args>
1033 requires std::is_constructible_v<E,
Args...>
1035 : has_val(
false), unex(std::forward<Args>(
args)...) {}
1037 template<
class U,
class...
Args>
1038 requires std::is_constructible_v<E, std::initializer_list<U>&,
Args...>
1041 unex(
il, std::forward<Args>(
args)...) {}
1045 if constexpr (std::is_trivially_destructible_v<E>) {
1047 if (!has_value()) std::destroy_at(std::addressof(this->unex));
1053 requires std::is_copy_assignable_v<E> &&
1054 std::is_copy_constructible_v<E>
1056 if (has_value() && rhs.has_value()) {
1057 }
else if (has_value()) {
1058 std::construct_at(std::addressof(this->unex), rhs.unex);
1060 }
else if (rhs.has_value()) {
1061 std::destroy_at(std::addressof(this->unex));
1064 this->unex = rhs.error();
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>
1074 if (has_value() && rhs.has_value()) {
1075 }
else if (has_value()) {
1076 std::construct_at(std::addressof(this->unex), std::move(rhs.unex));
1078 }
else if (rhs.has_value()) {
1079 std::destroy_at(std::addressof(this->unex));
1082 this->unex = std::move(rhs.error());
1088 requires std::is_constructible_v<E, G const&>
and
1089 std::is_assignable_v<E&, G const&>
1092 std::construct_at(std::addressof(this->unex),
1093 std::forward<G const&>(
e.value()));
1096 this->unex = std::forward<G const&>(
e.value());
1102 requires std::is_constructible_v<E, G> &&
1103 std::is_assignable_v<E&, G>
1106 std::construct_at(std::addressof(this->unex), std::forward<G>(
e.value()));
1109 this->unex = std::forward<G>(
e.value());
1115 constexpr void emplace()
noexcept {
1117 std::destroy_at(std::addressof(this->unex));
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>
1128 if (rhs.has_value()) {
1135 std::construct_at(std::addressof(this->unex), std::move(rhs.unex));
1136 std::destroy_at(std::addressof(rhs.unex));
1141 swap(this->unex, rhs.unex);
1147 constexpr explicit operator bool()
const noexcept {
return has_val; }
1149 [[
nodiscard]]
constexpr auto has_value()
const noexcept ->
bool {
1154 constexpr void operator*()
const noexcept {}
1156 constexpr void value()
const& {
1162 constexpr void value() && {
1169 constexpr auto error()
const& -> E
const& {
1170 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
1175 constexpr auto error() & -> E& {
1176 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
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);
1187 constexpr auto error() && -> E&& {
1188 PLUGIFY_ASSERT(!this->has_val,
"requires the expected to contain an error");
1189 return std::move(this->unex);
1193 template<
class F,
class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1195 std::is_same_v<typename U::error_type, E> &&
1196 std::is_copy_constructible_v<E>
1197 constexpr auto and_then(
F&& f) & {
1199 return std::invoke(std::forward<F>(f));
1201 return U(unexpect, error());
1204 template<
class F,
class U = std::remove_cvref_t<std::invoke_result_t<F>>>
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& {
1210 return std::invoke(std::forward<F>(f));
1212 return U(unexpect, error());
1215 template<
class F,
class U = std::remove_cvref_t<std::invoke_result_t<F>>>
1217 std::is_same_v<typename U::error_type, E> &&
1218 std::is_move_constructible_v<E>
1219 constexpr auto and_then(
F&& f) && {
1221 return std::invoke(std::forward<F>(f));
1223 return U(unexpect, std::move(error()));
1226 template<
class F,
class U = std::remove_cvref_t<std::invoke_result_t<F>>>
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&& {
1232 return std::invoke(std::forward<F>(f));
1234 return U(unexpect, std::move(error()));
1237 template<
class F,
class V = E&,
1238 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1240 std::is_same_v<typename G::value_type, void> &&
1241 std::is_copy_constructible_v<E>
1242 constexpr auto or_else(
F&& f) & {
1246 return std::invoke(std::forward<F>(f), error());
1249 template<
class F,
class V = E
const&,
1250 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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& {
1258 return std::invoke(std::forward<F>(f), error());
1261 template<
class F,
class V = E&&,
1262 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
1264 std::is_same_v<typename G::value_type, void> &&
1265 std::is_move_constructible_v<E>
1266 constexpr auto or_else(
F&& f) && {
1270 return std::invoke(std::forward<F>(f), std::move(error()));
1273 template<
class F,
class V = E
const&&,
1274 class G = std::remove_cvref_t<std::invoke_result_t<F, V>>>
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&& {
1282 return std::invoke(std::forward<F>(f), std::move(error()));
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) & {
1293 std::invoke(std::forward<F>(f), error());
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& {
1305 std::invoke(std::forward<F>(f), error());
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) && {
1319 std::invoke(std::forward<F>(f), error());
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&& {
1333 std::invoke(std::forward<F>(f), error());
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) & {
1341 if constexpr (!std::same_as<U, void>) {
1344 std::invoke(std::forward<F>(f));
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& {
1355 if constexpr (!std::same_as<U, void>) {
1358 std::invoke(std::forward<F>(f));
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) && {
1369 if constexpr (!std::same_as<U, void>) {
1372 std::invoke(std::forward<F>(f));
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&& {
1383 if constexpr (!std::same_as<U, void>) {
1386 std::invoke(std::forward<F>(f));
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) & {
1401 std::invoke(std::forward<F>(f), error()));
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& {
1412 std::invoke(std::forward<F>(f), error()));
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) && {
1423 unexpect, std::invoke(std::forward<F>(f), std::move(error())));
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&& {
1434 unexpect, std::invoke(std::forward<F>(f), std::move(error())));
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>;
1444 if (x.has_value() != y.has_value())
return false;
1445 return x.has_value()
or static_cast<bool>(x.error() == y.error());
1450 { x.error() ==
e.value() } -> std::convertible_to<bool>;
1454 return !x.has_value() &&
static_cast<bool>(x.error() ==
e.value());
1458 friend constexpr void swap(
expected& x,
1459 expected& y)
noexcept(
noexcept(x.swap(y))) {