217 using value_type = T;
218 using error_type = E;
222 template <
typename U = T,
typename std::enable_if_t<std::is_default_constructible_v<U>,
int> = 0>
223 constexpr expected() : has_(
true)
225 new (&storage_.value_) T();
228 template <
typename U = T,
typename std::enable_if_t<!std::is_default_constructible_v<U>,
int> = 0>
229 constexpr expected() =
delete;
231 constexpr expected(expected
const& other) : has_(other.has_)
234 new (&storage_.value_) T(other.storage_.value_);
236 new (&storage_.error_) E(other.storage_.error_);
239 constexpr expected(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
240 std::is_nothrow_move_constructible_v<E>)
244 new (&storage_.value_) T(std::move(other.storage_.value_));
246 new (&storage_.error_) E(std::move(other.storage_.error_));
249 template <
typename U = T,
250 typename = std::enable_if_t<
251 !std::is_same_v<std::decay_t<U>, expected> && !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
252 !std::is_same_v<std::decay_t<U>,
unexpected<E>> && std::is_constructible_v<T, U>>>
253# if __cplusplus >= 202002L
254 constexpr explicit(!std::is_convertible_v<U, T>) expected(U&& value) : has_(
true)
256 constexpr expected(U&& value, std::enable_if_t<std::is_convertible_v<U, T>,
int> = 0) : has_(
true)
258 new (&storage_.value_) T(std::forward<U>(value));
261 template <
typename U = T,
262 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> &&
263 !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
265 std::is_constructible_v<T, U> && !std::is_convertible_v<U, T>>>
266 constexpr explicit expected(U&& value) : has_(
true)
269 new (&storage_.value_) T(std::forward<U>(value));
272 template <
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
273 constexpr explicit expected(std::in_place_t , Args&&... args) : has_(
true)
275 new (&storage_.value_) T(std::forward<Args>(args)...);
280 new (&storage_.error_) E(ue.error());
285 new (&storage_.error_) E(std::move(ue.error()));
288 template <
typename... Args>
289 constexpr explicit expected(
unexpect_t , Args&&... args) : has_(
false)
291 new (&storage_.error_) E(std::forward<Args>(args)...);
295 constexpr auto operator=(expected
const& other) -> expected&
300 new (
this) expected(other);
304 constexpr auto operator=(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
305 std::is_nothrow_move_constructible_v<E>) -> expected&
310 new (
this) expected(std::move(other));
314 template <
typename U = T,
315 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> && std::is_constructible_v<T, U>>>
316 constexpr auto operator=(U&& value) -> expected&
320 storage_.value_.~T();
321 new (&storage_.value_) T(std::forward<U>(value));
326 new (
this) expected(std::forward<U>(value));
331 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
335 storage_.error_ = ue.error();
340 new (
this) expected(ue);
349 storage_.error_ = std::move(ue.error());
354 new (
this) expected(std::move(ue));
362 storage_.value_.~T();
364 storage_.error_.~E();
368 constexpr auto operator->()
const noexcept -> T
const*
370 return &storage_.value_;
373 constexpr auto operator->()
noexcept -> T*
375 return &storage_.value_;
378 constexpr auto operator*()
const&
noexcept -> T
const&
380 return storage_.value_;
383 constexpr auto operator*() &
noexcept -> T&
385 return storage_.value_;
388 constexpr auto operator*()
const&&
noexcept -> T
const&&
390 return std::move(storage_.value_);
393 constexpr auto operator*() &&
noexcept -> T&&
395 return std::move(storage_.value_);
398 constexpr explicit operator bool()
const noexcept
403 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
408 [[nodiscard]]
constexpr auto value()
const& -> T
const&
412 return storage_.value_;
415 constexpr auto value() & -> T&
419 return storage_.value_;
422 [[nodiscard]]
constexpr auto value()
const&& -> T
const&&
426 return std::move(storage_.value_);
429 constexpr auto value() && -> T&&
433 return std::move(storage_.value_);
436 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
438 return storage_.error_;
441 constexpr auto error() &
noexcept -> E&
443 return storage_.error_;
446 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
448 return std::move(storage_.error_);
451 constexpr auto error() &&
noexcept -> E&&
453 return std::move(storage_.error_);
456 template <
typename U>
457 constexpr auto value_or(U&& default_value)
const& -> T
459 return has_ ? storage_.value_ :
static_cast<T
>(std::forward<U>(default_value));
462 template <
typename U>
463 constexpr auto value_or(U&& default_value) && -> T
465 return has_ ? std::move(storage_.value_) :
static_cast<T
>(std::forward<U>(default_value));
469 template <
typename... Args>
470 constexpr auto emplace(Args&&... args) -> T&
473 new (
this) expected(std::in_place, std::forward<Args>(args)...);
474 return storage_.value_;
478 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
479 std::is_nothrow_move_constructible_v<E> &&
480 std::is_nothrow_swappable_v<T> && std::is_nothrow_swappable_v<E>)
482 if (has_ && other.has_)
485 swap(storage_.value_, other.storage_.value_);
487 else if (!has_ && !other.has_)
490 swap(storage_.error_, other.storage_.error_);
494 expected temp(std::move(other));
496 new (&other) expected(std::move(*
this));
498 new (
this) expected(std::move(temp));
503 template <
typename F>
504 constexpr auto and_then(F&& f) &
506 using U = std::invoke_result_t<F, T&>;
508 return std::invoke(std::forward<F>(f), storage_.value_);
509 return U(unexpect, storage_.error_);
512 template <
typename F>
513 constexpr auto and_then(F&& f)
const&
515 using U = std::invoke_result_t<F, T const&>;
517 return std::invoke(std::forward<F>(f), storage_.value_);
518 return U(unexpect, storage_.error_);
521 template <
typename F>
522 constexpr auto and_then(F&& f) &&
524 using U = std::invoke_result_t<F, T&&>;
526 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
527 return U(unexpect, std::move(storage_.error_));
530 template <
typename F>
531 constexpr auto and_then(F&& f)
const&&
533 using U = std::invoke_result_t<F, T const&&>;
535 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
536 return U(unexpect, std::move(storage_.error_));
539 template <
typename F>
540 constexpr auto or_else(F&& f) &
542 using U = std::invoke_result_t<F, E&>;
544 return U(storage_.value_);
545 return std::invoke(std::forward<F>(f), storage_.error_);
548 template <
typename F>
549 constexpr auto or_else(F&& f)
const&
551 using U = std::invoke_result_t<F, E const&>;
553 return U(storage_.value_);
554 return std::invoke(std::forward<F>(f), storage_.error_);
557 template <
typename F>
558 constexpr auto or_else(F&& f) &&
560 using U = std::invoke_result_t<F, E&&>;
562 return U(std::move(storage_.value_));
563 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
566 template <
typename F>
567 constexpr auto or_else(F&& f)
const&&
569 using U = std::invoke_result_t<F, E const&&>;
571 return U(std::move(storage_.value_));
572 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
575 template <
typename F>
576 constexpr auto transform(F&& f) &
578 using U = std::remove_cv_t<std::invoke_result_t<F, T&>>;
580 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
581 return expected<U, E>(unexpect, storage_.error_);
584 template <
typename F>
585 constexpr auto transform(F&& f)
const&
587 using U = std::remove_cv_t<std::invoke_result_t<F, T const&>>;
589 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
590 return expected<U, E>(unexpect, storage_.error_);
593 template <
typename F>
594 constexpr auto transform(F&& f) &&
596 using U = std::remove_cv_t<std::invoke_result_t<F, T&&>>;
598 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
599 return expected<U, E>(unexpect, std::move(storage_.error_));
602 template <
typename F>
603 constexpr auto transform(F&& f)
const&&
605 using U = std::remove_cv_t<std::invoke_result_t<F, T const&&>>;
607 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
608 return expected<U, E>(unexpect, std::move(storage_.error_));
611 template <
typename F>
612 constexpr auto transform_error(F&& f) &
614 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
616 return expected<T, G>(storage_.value_);
617 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
620 template <
typename F>
621 constexpr auto transform_error(F&& f)
const&
623 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
625 return expected<T, G>(storage_.value_);
626 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
629 template <
typename F>
630 constexpr auto transform_error(F&& f) &&
632 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
634 return expected<T, G>(std::move(storage_.value_));
635 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
638 template <
typename F>
639 constexpr auto transform_error(F&& f)
const&&
641 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
643 return expected<T, G>(std::move(storage_.value_));
644 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
648 template <
typename T2,
typename E2>
649 constexpr friend auto operator==(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
651 if (lhs.has_value() != rhs.has_value())
655 return lhs.error() == rhs.error();
658 template <
typename T2,
typename E2>
659 constexpr friend auto operator!=(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
661 return !(lhs == rhs);
664 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
665 constexpr friend auto operator==(expected
const& lhs,
const T2& rhs) ->
bool
667 return lhs.has_value() && *lhs == rhs;
670 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
671 constexpr friend auto operator==(
const T2& lhs, expected
const& rhs) ->
bool
673 return rhs.has_value() && lhs == *rhs;
676 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
677 constexpr friend auto operator!=(expected
const& lhs,
const T2& rhs) ->
bool
679 return !(lhs == rhs);
682 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
683 constexpr friend auto operator!=(
const T2& lhs, expected
const& rhs) ->
bool
685 return !(lhs == rhs);
688 template <
typename E2>
689 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
691 return !lhs.has_value() && lhs.error() == rhs.error();
694 template <
typename E2>
695 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
697 return !rhs.has_value() && lhs.error() == rhs.error();
700 template <
typename E2>
701 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
703 return !(lhs == rhs);
706 template <
typename E2>
707 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
709 return !(lhs == rhs);
735class expected<void, E>
738 using value_type = void;
739 using error_type = E;
742 constexpr expected() : has_(
true)
746 constexpr expected(expected
const& other) =
default;
747 constexpr expected(expected&& other) =
default;
749 template <
typename... Args>
750 constexpr explicit expected(
unexpect_t , Args&&... args)
751 : has_(
false), error_(std::forward<Args>(args)...)
755 constexpr expected(
unexpected<E> const& ue) : has_(
false), error_(ue.error())
759 constexpr expected(
unexpected<E>&& ue) : has_(
false), error_(std::move(ue.error()))
763 constexpr auto operator=(expected
const& other) -> expected& =
default;
764 constexpr auto operator=(expected&& other) -> expected& =
default;
766 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
776 error_ = std::move(ue.error());
780 constexpr explicit operator bool()
const noexcept
785 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
790 constexpr void value()
const
796 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
801 constexpr auto error() &
noexcept -> E&
806 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
808 return std::move(error_);
811 constexpr auto error() &&
noexcept -> E&&
813 return std::move(error_);
816 constexpr void emplace()
821 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<E> &&
822 std::is_nothrow_swappable_v<E>)
824 if (has_ && other.has_)
828 else if (!has_ && !other.has_)
831 swap(error_, other.error_);
835 std::swap(has_, other.has_);
836 std::swap(error_, other.error_);
841 template <
typename F>
842 constexpr auto and_then(F&& f) &
844 using U = std::invoke_result_t<F>;
846 return std::invoke(std::forward<F>(f));
847 return U(unexpect, error_);
850 template <
typename F>
851 constexpr auto and_then(F&& f)
const&
853 using U = std::invoke_result_t<F>;
855 return std::invoke(std::forward<F>(f));
856 return U(unexpect, error_);
859 template <
typename F>
860 constexpr auto and_then(F&& f) &&
862 using U = std::invoke_result_t<F>;
864 return std::invoke(std::forward<F>(f));
865 return U(unexpect, std::move(error_));
868 template <
typename F>
869 constexpr auto and_then(F&& f)
const&&
871 using U = std::invoke_result_t<F>;
873 return std::invoke(std::forward<F>(f));
874 return U(unexpect, std::move(error_));
877 template <
typename F>
878 constexpr auto or_else(F&& f) &
880 using U = std::invoke_result_t<F, E&>;
883 return std::invoke(std::forward<F>(f), error_);
886 template <
typename F>
887 constexpr auto or_else(F&& f)
const&
889 using U = std::invoke_result_t<F, E const&>;
892 return std::invoke(std::forward<F>(f), error_);
895 template <
typename F>
896 constexpr auto or_else(F&& f) &&
898 using U = std::invoke_result_t<F, E&&>;
901 return std::invoke(std::forward<F>(f), std::move(error_));
904 template <
typename F>
905 constexpr auto or_else(F&& f)
const&&
907 using U = std::invoke_result_t<F, E const&&>;
910 return std::invoke(std::forward<F>(f), std::move(error_));
913 template <
typename F>
914 constexpr auto transform(F&& f) &
916 using U = std::remove_cv_t<std::invoke_result_t<F>>;
918 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
919 return expected<U, E>(unexpect, error_);
922 template <
typename F>
923 constexpr auto transform(F&& f)
const&
925 using U = std::remove_cv_t<std::invoke_result_t<F>>;
927 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
928 return expected<U, E>(unexpect, error_);
931 template <
typename F>
932 constexpr auto transform(F&& f) &&
934 using U = std::remove_cv_t<std::invoke_result_t<F>>;
936 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
937 return expected<U, E>(unexpect, std::move(error_));
940 template <
typename F>
941 constexpr auto transform(F&& f)
const&&
943 using U = std::remove_cv_t<std::invoke_result_t<F>>;
945 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
946 return expected<U, E>(unexpect, std::move(error_));
949 template <
typename F>
950 constexpr auto transform_error(F&& f) &
952 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
954 return expected<void, G>();
955 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
958 template <
typename F>
959 constexpr auto transform_error(F&& f)
const&
961 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
963 return expected<void, G>();
964 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
967 template <
typename F>
968 constexpr auto transform_error(F&& f) &&
970 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
972 return expected<void, G>();
973 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
976 template <
typename F>
977 constexpr auto transform_error(F&& f)
const&&
979 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
981 return expected<void, G>();
982 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
986 template <
typename E2>
987 constexpr friend auto operator==(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
989 if (lhs.has_value() != rhs.has_value())
993 return lhs.error() == rhs.error();
996 template <
typename E2>
997 constexpr friend auto operator!=(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
999 return !(lhs == rhs);
1002 template <
typename E2>
1003 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
1005 return !lhs.has_value() && lhs.error() == rhs.error();
1008 template <
typename E2>
1009 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
1011 return !rhs.has_value() && lhs.error() == rhs.error();
1014 template <
typename E2>
1015 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
1017 return !(lhs == rhs);
1020 template <
typename E2>
1021 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
1023 return !(lhs == rhs);