136 using value_type = T;
137 using error_type = E;
141 template <
typename U = T,
typename std::enable_if_t<std::is_default_constructible_v<U>,
int> = 0>
142 constexpr expected() : has_(
true)
144 new (&storage_.value_) T();
147 template <
typename U = T,
typename std::enable_if_t<!std::is_default_constructible_v<U>,
int> = 0>
148 constexpr expected() =
delete;
150 constexpr expected(expected
const& other) : has_(other.has_)
153 new (&storage_.value_) T(other.storage_.value_);
155 new (&storage_.error_) E(other.storage_.error_);
158 constexpr expected(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
159 std::is_nothrow_move_constructible_v<E>)
163 new (&storage_.value_) T(std::move(other.storage_.value_));
165 new (&storage_.error_) E(std::move(other.storage_.error_));
168 template <
typename U = T,
169 typename = std::enable_if_t<
170 !std::is_same_v<std::decay_t<U>, expected> && !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
171 !std::is_same_v<std::decay_t<U>,
unexpected<E>> && std::is_constructible_v<T, U>>>
172# if __cplusplus >= 202002L
173 constexpr explicit(!std::is_convertible_v<U, T>) expected(U&& value) : has_(
true)
175 constexpr expected(U&& value, std::enable_if_t<std::is_convertible_v<U, T>,
int> = 0) : has_(
true)
177 new (&storage_.value_) T(std::forward<U>(value));
180 template <
typename U = T,
181 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> &&
182 !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
184 std::is_constructible_v<T, U> && !std::is_convertible_v<U, T>>>
185 constexpr explicit expected(U&& value) : has_(
true)
188 new (&storage_.value_) T(std::forward<U>(value));
191 template <
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
192 constexpr explicit expected(std::in_place_t , Args&&... args) : has_(
true)
194 new (&storage_.value_) T(std::forward<Args>(args)...);
199 new (&storage_.error_) E(ue.error());
204 new (&storage_.error_) E(std::move(ue.error()));
207 template <
typename... Args>
208 constexpr explicit expected(
unexpect_t , Args&&... args) : has_(
false)
210 new (&storage_.error_) E(std::forward<Args>(args)...);
214 constexpr auto operator=(expected
const& other) -> expected&
219 new (
this) expected(other);
223 constexpr auto operator=(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
224 std::is_nothrow_move_constructible_v<E>) -> expected&
229 new (
this) expected(std::move(other));
233 template <
typename U = T,
234 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> && std::is_constructible_v<T, U>>>
235 constexpr auto operator=(U&& value) -> expected&
239 storage_.value_.~T();
240 new (&storage_.value_) T(std::forward<U>(value));
245 new (
this) expected(std::forward<U>(value));
250 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
254 storage_.error_ = ue.error();
259 new (
this) expected(ue);
268 storage_.error_ = std::move(ue.error());
273 new (
this) expected(std::move(ue));
281 storage_.value_.~T();
283 storage_.error_.~E();
287 constexpr auto operator->()
const noexcept -> T
const*
289 return &storage_.value_;
292 constexpr auto operator->()
noexcept -> T*
294 return &storage_.value_;
297 constexpr auto operator*()
const&
noexcept -> T
const&
299 return storage_.value_;
302 constexpr auto operator*() &
noexcept -> T&
304 return storage_.value_;
307 constexpr auto operator*()
const&&
noexcept -> T
const&&
309 return std::move(storage_.value_);
312 constexpr auto operator*() &&
noexcept -> T&&
314 return std::move(storage_.value_);
317 constexpr explicit operator bool()
const noexcept
322 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
327 [[nodiscard]]
constexpr auto value()
const& -> T
const&
331 return storage_.value_;
334 constexpr auto value() & -> T&
338 return storage_.value_;
341 [[nodiscard]]
constexpr auto value()
const&& -> T
const&&
345 return std::move(storage_.value_);
348 constexpr auto value() && -> T&&
352 return std::move(storage_.value_);
355 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
357 return storage_.error_;
360 constexpr auto error() &
noexcept -> E&
362 return storage_.error_;
365 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
367 return std::move(storage_.error_);
370 constexpr auto error() &&
noexcept -> E&&
372 return std::move(storage_.error_);
375 template <
typename U>
376 constexpr auto value_or(U&& default_value)
const& -> T
378 return has_ ? storage_.value_ :
static_cast<T
>(std::forward<U>(default_value));
381 template <
typename U>
382 constexpr auto value_or(U&& default_value) && -> T
384 return has_ ? std::move(storage_.value_) :
static_cast<T
>(std::forward<U>(default_value));
388 template <
typename... Args>
389 constexpr auto emplace(Args&&... args) -> T&
392 new (
this) expected(std::in_place, std::forward<Args>(args)...);
393 return storage_.value_;
397 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
398 std::is_nothrow_move_constructible_v<E> &&
399 std::is_nothrow_swappable_v<T> && std::is_nothrow_swappable_v<E>)
401 if (has_ && other.has_)
404 swap(storage_.value_, other.storage_.value_);
406 else if (!has_ && !other.has_)
409 swap(storage_.error_, other.storage_.error_);
413 expected temp(std::move(other));
415 new (&other) expected(std::move(*
this));
417 new (
this) expected(std::move(temp));
422 template <
typename F>
423 constexpr auto and_then(F&& f) &
425 using U = std::invoke_result_t<F, T&>;
427 return std::invoke(std::forward<F>(f), storage_.value_);
428 return U(unexpect, storage_.error_);
431 template <
typename F>
432 constexpr auto and_then(F&& f)
const&
434 using U = std::invoke_result_t<F, T const&>;
436 return std::invoke(std::forward<F>(f), storage_.value_);
437 return U(unexpect, storage_.error_);
440 template <
typename F>
441 constexpr auto and_then(F&& f) &&
443 using U = std::invoke_result_t<F, T&&>;
445 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
446 return U(unexpect, std::move(storage_.error_));
449 template <
typename F>
450 constexpr auto and_then(F&& f)
const&&
452 using U = std::invoke_result_t<F, T const&&>;
454 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
455 return U(unexpect, std::move(storage_.error_));
458 template <
typename F>
459 constexpr auto or_else(F&& f) &
461 using U = std::invoke_result_t<F, E&>;
463 return U(storage_.value_);
464 return std::invoke(std::forward<F>(f), storage_.error_);
467 template <
typename F>
468 constexpr auto or_else(F&& f)
const&
470 using U = std::invoke_result_t<F, E const&>;
472 return U(storage_.value_);
473 return std::invoke(std::forward<F>(f), storage_.error_);
476 template <
typename F>
477 constexpr auto or_else(F&& f) &&
479 using U = std::invoke_result_t<F, E&&>;
481 return U(std::move(storage_.value_));
482 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
485 template <
typename F>
486 constexpr auto or_else(F&& f)
const&&
488 using U = std::invoke_result_t<F, E const&&>;
490 return U(std::move(storage_.value_));
491 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
494 template <
typename F>
495 constexpr auto transform(F&& f) &
497 using U = std::remove_cv_t<std::invoke_result_t<F, T&>>;
499 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
500 return expected<U, E>(unexpect, storage_.error_);
503 template <
typename F>
504 constexpr auto transform(F&& f)
const&
506 using U = std::remove_cv_t<std::invoke_result_t<F, T const&>>;
508 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
509 return expected<U, E>(unexpect, storage_.error_);
512 template <
typename F>
513 constexpr auto transform(F&& f) &&
515 using U = std::remove_cv_t<std::invoke_result_t<F, T&&>>;
517 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
518 return expected<U, E>(unexpect, std::move(storage_.error_));
521 template <
typename F>
522 constexpr auto transform(F&& f)
const&&
524 using U = std::remove_cv_t<std::invoke_result_t<F, T const&&>>;
526 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
527 return expected<U, E>(unexpect, std::move(storage_.error_));
530 template <
typename F>
531 constexpr auto transform_error(F&& f) &
533 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
535 return expected<T, G>(storage_.value_);
536 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
539 template <
typename F>
540 constexpr auto transform_error(F&& f)
const&
542 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
544 return expected<T, G>(storage_.value_);
545 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
548 template <
typename F>
549 constexpr auto transform_error(F&& f) &&
551 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
553 return expected<T, G>(std::move(storage_.value_));
554 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
557 template <
typename F>
558 constexpr auto transform_error(F&& f)
const&&
560 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
562 return expected<T, G>(std::move(storage_.value_));
563 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
567 template <
typename T2,
typename E2>
568 constexpr friend auto operator==(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
570 if (lhs.has_value() != rhs.has_value())
574 return lhs.error() == rhs.error();
577 template <
typename T2,
typename E2>
578 constexpr friend auto operator!=(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
580 return !(lhs == rhs);
583 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
584 constexpr friend auto operator==(expected
const& lhs,
const T2& rhs) ->
bool
586 return lhs.has_value() && *lhs == rhs;
589 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
590 constexpr friend auto operator==(
const T2& lhs, expected
const& rhs) ->
bool
592 return rhs.has_value() && lhs == *rhs;
595 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
596 constexpr friend auto operator!=(expected
const& lhs,
const T2& rhs) ->
bool
598 return !(lhs == rhs);
601 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
602 constexpr friend auto operator!=(
const T2& lhs, expected
const& rhs) ->
bool
604 return !(lhs == rhs);
607 template <
typename E2>
608 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
610 return !lhs.has_value() && lhs.error() == rhs.error();
613 template <
typename E2>
614 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
616 return !rhs.has_value() && lhs.error() == rhs.error();
619 template <
typename E2>
620 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
622 return !(lhs == rhs);
625 template <
typename E2>
626 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
628 return !(lhs == rhs);
642class expected<void, E>
645 using value_type = void;
646 using error_type = E;
649 constexpr expected() : has_(
true)
653 constexpr expected(expected
const& other) =
default;
654 constexpr expected(expected&& other) =
default;
656 template <
typename... Args>
657 constexpr explicit expected(
unexpect_t , Args&&... args)
658 : has_(
false), error_(std::forward<Args>(args)...)
662 constexpr expected(
unexpected<E> const& ue) : has_(
false), error_(ue.error())
666 constexpr expected(
unexpected<E>&& ue) : has_(
false), error_(std::move(ue.error()))
670 constexpr auto operator=(expected
const& other) -> expected& =
default;
671 constexpr auto operator=(expected&& other) -> expected& =
default;
673 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
683 error_ = std::move(ue.error());
687 constexpr explicit operator bool()
const noexcept
692 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
697 constexpr void value()
const
703 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
708 constexpr auto error() &
noexcept -> E&
713 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
715 return std::move(error_);
718 constexpr auto error() &&
noexcept -> E&&
720 return std::move(error_);
723 constexpr void emplace()
728 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<E> &&
729 std::is_nothrow_swappable_v<E>)
731 if (has_ && other.has_)
735 else if (!has_ && !other.has_)
738 swap(error_, other.error_);
742 std::swap(has_, other.has_);
743 std::swap(error_, other.error_);
748 template <
typename F>
749 constexpr auto and_then(F&& f) &
751 using U = std::invoke_result_t<F>;
753 return std::invoke(std::forward<F>(f));
754 return U(unexpect, error_);
757 template <
typename F>
758 constexpr auto and_then(F&& f)
const&
760 using U = std::invoke_result_t<F>;
762 return std::invoke(std::forward<F>(f));
763 return U(unexpect, error_);
766 template <
typename F>
767 constexpr auto and_then(F&& f) &&
769 using U = std::invoke_result_t<F>;
771 return std::invoke(std::forward<F>(f));
772 return U(unexpect, std::move(error_));
775 template <
typename F>
776 constexpr auto and_then(F&& f)
const&&
778 using U = std::invoke_result_t<F>;
780 return std::invoke(std::forward<F>(f));
781 return U(unexpect, std::move(error_));
784 template <
typename F>
785 constexpr auto or_else(F&& f) &
787 using U = std::invoke_result_t<F, E&>;
790 return std::invoke(std::forward<F>(f), error_);
793 template <
typename F>
794 constexpr auto or_else(F&& f)
const&
796 using U = std::invoke_result_t<F, E const&>;
799 return std::invoke(std::forward<F>(f), error_);
802 template <
typename F>
803 constexpr auto or_else(F&& f) &&
805 using U = std::invoke_result_t<F, E&&>;
808 return std::invoke(std::forward<F>(f), std::move(error_));
811 template <
typename F>
812 constexpr auto or_else(F&& f)
const&&
814 using U = std::invoke_result_t<F, E const&&>;
817 return std::invoke(std::forward<F>(f), std::move(error_));
820 template <
typename F>
821 constexpr auto transform(F&& f) &
823 using U = std::remove_cv_t<std::invoke_result_t<F>>;
825 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
826 return expected<U, E>(unexpect, error_);
829 template <
typename F>
830 constexpr auto transform(F&& f)
const&
832 using U = std::remove_cv_t<std::invoke_result_t<F>>;
834 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
835 return expected<U, E>(unexpect, error_);
838 template <
typename F>
839 constexpr auto transform(F&& f) &&
841 using U = std::remove_cv_t<std::invoke_result_t<F>>;
843 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
844 return expected<U, E>(unexpect, std::move(error_));
847 template <
typename F>
848 constexpr auto transform(F&& f)
const&&
850 using U = std::remove_cv_t<std::invoke_result_t<F>>;
852 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
853 return expected<U, E>(unexpect, std::move(error_));
856 template <
typename F>
857 constexpr auto transform_error(F&& f) &
859 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
861 return expected<void, G>();
862 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
865 template <
typename F>
866 constexpr auto transform_error(F&& f)
const&
868 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
870 return expected<void, G>();
871 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
874 template <
typename F>
875 constexpr auto transform_error(F&& f) &&
877 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
879 return expected<void, G>();
880 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
883 template <
typename F>
884 constexpr auto transform_error(F&& f)
const&&
886 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
888 return expected<void, G>();
889 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
893 template <
typename E2>
894 constexpr friend auto operator==(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
896 if (lhs.has_value() != rhs.has_value())
900 return lhs.error() == rhs.error();
903 template <
typename E2>
904 constexpr friend auto operator!=(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
906 return !(lhs == rhs);
909 template <
typename E2>
910 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
912 return !lhs.has_value() && lhs.error() == rhs.error();
915 template <
typename E2>
916 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
918 return !rhs.has_value() && lhs.error() == rhs.error();
921 template <
typename E2>
922 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
924 return !(lhs == rhs);
927 template <
typename E2>
928 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
930 return !(lhs == rhs);