126 using value_type = T;
127 using error_type = E;
131 template <
typename U = T,
typename std::enable_if_t<std::is_default_constructible_v<U>,
int> = 0>
132 constexpr expected() : has_(
true)
134 new (&storage_.value_) T();
137 template <
typename U = T,
typename std::enable_if_t<!std::is_default_constructible_v<U>,
int> = 0>
138 constexpr expected() =
delete;
140 constexpr expected(expected
const& other) : has_(other.has_)
143 new (&storage_.value_) T(other.storage_.value_);
145 new (&storage_.error_) E(other.storage_.error_);
148 constexpr expected(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
149 std::is_nothrow_move_constructible_v<E>)
153 new (&storage_.value_) T(std::move(other.storage_.value_));
155 new (&storage_.error_) E(std::move(other.storage_.error_));
158 template <
typename U = T,
159 typename = std::enable_if_t<
160 !std::is_same_v<std::decay_t<U>, expected> && !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
161 !std::is_same_v<std::decay_t<U>,
unexpected<E>> && std::is_constructible_v<T, U>>>
162#if __cplusplus >= 202002L
163 constexpr explicit(!std::is_convertible_v<U, T>) expected(U&& value) : has_(
true)
165 constexpr expected(U&& value, std::enable_if_t<std::is_convertible_v<U, T>,
int> = 0) : has_(
true)
167 new (&storage_.value_) T(std::forward<U>(value));
170 template <
typename U = T,
171 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> &&
172 !std::is_same_v<std::decay_t<U>, std::in_place_t> &&
174 std::is_constructible_v<T, U> && !std::is_convertible_v<U, T>>>
175 constexpr explicit expected(U&& value) : has_(
true)
178 new (&storage_.value_) T(std::forward<U>(value));
181 template <
typename... Args,
typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
182 constexpr explicit expected(std::in_place_t , Args&&... args) : has_(
true)
184 new (&storage_.value_) T(std::forward<Args>(args)...);
189 new (&storage_.error_) E(ue.error());
194 new (&storage_.error_) E(std::move(ue.error()));
197 template <
typename... Args>
198 constexpr explicit expected(
unexpect_t , Args&&... args) : has_(
false)
200 new (&storage_.error_) E(std::forward<Args>(args)...);
204 constexpr auto operator=(expected
const& other) -> expected&
209 new (
this) expected(other);
213 constexpr auto operator=(expected&& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
214 std::is_nothrow_move_constructible_v<E>) -> expected&
219 new (
this) expected(std::move(other));
223 template <
typename U = T,
224 typename = std::enable_if_t<!std::is_same_v<std::decay_t<U>, expected> && std::is_constructible_v<T, U>>>
225 constexpr auto operator=(U&& value) -> expected&
229 storage_.value_.~T();
230 new (&storage_.value_) T(std::forward<U>(value));
235 new (
this) expected(std::forward<U>(value));
240 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
244 storage_.error_ = ue.error();
249 new (
this) expected(ue);
258 storage_.error_ = std::move(ue.error());
263 new (
this) expected(std::move(ue));
271 storage_.value_.~T();
273 storage_.error_.~E();
277 constexpr auto operator->()
const noexcept -> T
const*
279 return &storage_.value_;
282 constexpr auto operator->()
noexcept -> T*
284 return &storage_.value_;
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 std::move(storage_.value_);
302 constexpr auto operator*() &&
noexcept -> T&&
304 return std::move(storage_.value_);
307 constexpr explicit operator bool()
const noexcept
312 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
317 [[nodiscard]]
constexpr auto value()
const& -> T
const&
321 return storage_.value_;
324 constexpr auto value() & -> T&
328 return storage_.value_;
331 [[nodiscard]]
constexpr auto value()
const&& -> T
const&&
335 return std::move(storage_.value_);
338 constexpr auto value() && -> T&&
342 return std::move(storage_.value_);
345 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
347 return storage_.error_;
350 constexpr auto error() &
noexcept -> E&
352 return storage_.error_;
355 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
357 return std::move(storage_.error_);
360 constexpr auto error() &&
noexcept -> E&&
362 return std::move(storage_.error_);
365 template <
typename U>
366 constexpr auto value_or(U&& default_value)
const& -> T
368 return has_ ? storage_.value_ :
static_cast<T
>(std::forward<U>(default_value));
371 template <
typename U>
372 constexpr auto value_or(U&& default_value) && -> T
374 return has_ ? std::move(storage_.value_) :
static_cast<T
>(std::forward<U>(default_value));
378 template <
typename... Args>
379 constexpr auto emplace(Args&&... args) -> T&
382 new (
this) expected(std::in_place, std::forward<Args>(args)...);
383 return storage_.value_;
387 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<T> &&
388 std::is_nothrow_move_constructible_v<E> &&
389 std::is_nothrow_swappable_v<T> && std::is_nothrow_swappable_v<E>)
391 if (has_ && other.has_)
394 swap(storage_.value_, other.storage_.value_);
396 else if (!has_ && !other.has_)
399 swap(storage_.error_, other.storage_.error_);
403 expected temp(std::move(other));
405 new (&other) expected(std::move(*
this));
407 new (
this) expected(std::move(temp));
412 template <
typename F>
413 constexpr auto and_then(F&& f) &
415 using U = std::invoke_result_t<F, T&>;
417 return std::invoke(std::forward<F>(f), storage_.value_);
418 return U(unexpect, storage_.error_);
421 template <
typename F>
422 constexpr auto and_then(F&& f)
const&
424 using U = std::invoke_result_t<F, T const&>;
426 return std::invoke(std::forward<F>(f), storage_.value_);
427 return U(unexpect, storage_.error_);
430 template <
typename F>
431 constexpr auto and_then(F&& f) &&
433 using U = std::invoke_result_t<F, T&&>;
435 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
436 return U(unexpect, std::move(storage_.error_));
439 template <
typename F>
440 constexpr auto and_then(F&& f)
const&&
442 using U = std::invoke_result_t<F, T const&&>;
444 return std::invoke(std::forward<F>(f), std::move(storage_.value_));
445 return U(unexpect, std::move(storage_.error_));
448 template <
typename F>
449 constexpr auto or_else(F&& f) &
451 using U = std::invoke_result_t<F, E&>;
453 return U(storage_.value_);
454 return std::invoke(std::forward<F>(f), storage_.error_);
457 template <
typename F>
458 constexpr auto or_else(F&& f)
const&
460 using U = std::invoke_result_t<F, E const&>;
462 return U(storage_.value_);
463 return std::invoke(std::forward<F>(f), storage_.error_);
466 template <
typename F>
467 constexpr auto or_else(F&& f) &&
469 using U = std::invoke_result_t<F, E&&>;
471 return U(std::move(storage_.value_));
472 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
475 template <
typename F>
476 constexpr auto or_else(F&& f)
const&&
478 using U = std::invoke_result_t<F, E const&&>;
480 return U(std::move(storage_.value_));
481 return std::invoke(std::forward<F>(f), std::move(storage_.error_));
484 template <
typename F>
485 constexpr auto transform(F&& f) &
487 using U = std::remove_cv_t<std::invoke_result_t<F, T&>>;
489 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
490 return expected<U, E>(unexpect, storage_.error_);
493 template <
typename F>
494 constexpr auto transform(F&& f)
const&
496 using U = std::remove_cv_t<std::invoke_result_t<F, T const&>>;
498 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), storage_.value_));
499 return expected<U, E>(unexpect, storage_.error_);
502 template <
typename F>
503 constexpr auto transform(F&& f) &&
505 using U = std::remove_cv_t<std::invoke_result_t<F, T&&>>;
507 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
508 return expected<U, E>(unexpect, std::move(storage_.error_));
511 template <
typename F>
512 constexpr auto transform(F&& f)
const&&
514 using U = std::remove_cv_t<std::invoke_result_t<F, T const&&>>;
516 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f), std::move(storage_.value_)));
517 return expected<U, E>(unexpect, std::move(storage_.error_));
520 template <
typename F>
521 constexpr auto transform_error(F&& f) &
523 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
525 return expected<T, G>(storage_.value_);
526 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
529 template <
typename F>
530 constexpr auto transform_error(F&& f)
const&
532 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
534 return expected<T, G>(storage_.value_);
535 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), storage_.error_));
538 template <
typename F>
539 constexpr auto transform_error(F&& f) &&
541 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
543 return expected<T, G>(std::move(storage_.value_));
544 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
547 template <
typename F>
548 constexpr auto transform_error(F&& f)
const&&
550 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
552 return expected<T, G>(std::move(storage_.value_));
553 return expected<T, G>(unexpect, std::invoke(std::forward<F>(f), std::move(storage_.error_)));
557 template <
typename T2,
typename E2>
558 constexpr friend auto operator==(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
560 if (lhs.has_value() != rhs.has_value())
564 return lhs.error() == rhs.error();
567 template <
typename T2,
typename E2>
568 constexpr friend auto operator!=(expected
const& lhs, expected<T2, E2>
const& rhs) ->
bool
570 return !(lhs == rhs);
573 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
574 constexpr friend auto operator==(expected
const& lhs,
const T2& rhs) ->
bool
576 return lhs.has_value() && *lhs == rhs;
579 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
580 constexpr friend auto operator==(
const T2& lhs, expected
const& rhs) ->
bool
582 return rhs.has_value() && lhs == *rhs;
585 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
586 constexpr friend auto operator!=(expected
const& lhs,
const T2& rhs) ->
bool
588 return !(lhs == rhs);
591 template <
typename T2,
typename = std::enable_if_t<!std::is_same_v<expected, std::decay_t<T2>>>>
592 constexpr friend auto operator!=(
const T2& lhs, expected
const& rhs) ->
bool
594 return !(lhs == rhs);
597 template <
typename E2>
598 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
600 return !lhs.has_value() && lhs.error() == rhs.error();
603 template <
typename E2>
604 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
606 return !rhs.has_value() && lhs.error() == rhs.error();
609 template <
typename E2>
610 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
612 return !(lhs == rhs);
615 template <
typename E2>
616 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
618 return !(lhs == rhs);
636class expected<void, E>
639 using value_type = void;
640 using error_type = E;
643 constexpr expected() : has_(
true)
647 constexpr expected(expected
const& other) =
default;
648 constexpr expected(expected&& other) =
default;
650 template <
typename... Args>
651 constexpr explicit expected(
unexpect_t , Args&&... args)
652 : has_(
false), error_(std::forward<Args>(args)...)
656 constexpr expected(
unexpected<E> const& ue) : has_(
false), error_(ue.error())
660 constexpr expected(
unexpected<E>&& ue) : has_(
false), error_(std::move(ue.error()))
664 constexpr auto operator=(expected
const& other) -> expected& =
default;
665 constexpr auto operator=(expected&& other) -> expected& =
default;
667 constexpr auto operator=(
unexpected<E> const& ue) -> expected&
677 error_ = std::move(ue.error());
681 constexpr explicit operator bool()
const noexcept
686 [[nodiscard]]
constexpr auto has_value()
const noexcept ->
bool
691 constexpr void value()
const
697 [[nodiscard]]
constexpr auto error()
const&
noexcept -> E
const&
702 constexpr auto error() &
noexcept -> E&
707 [[nodiscard]]
constexpr auto error()
const&&
noexcept -> E
const&&
709 return std::move(error_);
712 constexpr auto error() &&
noexcept -> E&&
714 return std::move(error_);
717 constexpr void emplace()
722 constexpr void swap(expected& other)
noexcept(std::is_nothrow_move_constructible_v<E> &&
723 std::is_nothrow_swappable_v<E>)
725 if (has_ && other.has_)
729 else if (!has_ && !other.has_)
732 swap(error_, other.error_);
736 std::swap(has_, other.has_);
737 std::swap(error_, other.error_);
742 template <
typename F>
743 constexpr auto and_then(F&& f) &
745 using U = std::invoke_result_t<F>;
747 return std::invoke(std::forward<F>(f));
748 return U(unexpect, error_);
751 template <
typename F>
752 constexpr auto and_then(F&& f)
const&
754 using U = std::invoke_result_t<F>;
756 return std::invoke(std::forward<F>(f));
757 return U(unexpect, error_);
760 template <
typename F>
761 constexpr auto and_then(F&& f) &&
763 using U = std::invoke_result_t<F>;
765 return std::invoke(std::forward<F>(f));
766 return U(unexpect, std::move(error_));
769 template <
typename F>
770 constexpr auto and_then(F&& f)
const&&
772 using U = std::invoke_result_t<F>;
774 return std::invoke(std::forward<F>(f));
775 return U(unexpect, std::move(error_));
778 template <
typename F>
779 constexpr auto or_else(F&& f) &
781 using U = std::invoke_result_t<F, E&>;
784 return std::invoke(std::forward<F>(f), error_);
787 template <
typename F>
788 constexpr auto or_else(F&& f)
const&
790 using U = std::invoke_result_t<F, E const&>;
793 return std::invoke(std::forward<F>(f), error_);
796 template <
typename F>
797 constexpr auto or_else(F&& f) &&
799 using U = std::invoke_result_t<F, E&&>;
802 return std::invoke(std::forward<F>(f), std::move(error_));
805 template <
typename F>
806 constexpr auto or_else(F&& f)
const&&
808 using U = std::invoke_result_t<F, E const&&>;
811 return std::invoke(std::forward<F>(f), std::move(error_));
814 template <
typename F>
815 constexpr auto transform(F&& f) &
817 using U = std::remove_cv_t<std::invoke_result_t<F>>;
819 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
820 return expected<U, E>(unexpect, error_);
823 template <
typename F>
824 constexpr auto transform(F&& f)
const&
826 using U = std::remove_cv_t<std::invoke_result_t<F>>;
828 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
829 return expected<U, E>(unexpect, error_);
832 template <
typename F>
833 constexpr auto transform(F&& f) &&
835 using U = std::remove_cv_t<std::invoke_result_t<F>>;
837 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
838 return expected<U, E>(unexpect, std::move(error_));
841 template <
typename F>
842 constexpr auto transform(F&& f)
const&&
844 using U = std::remove_cv_t<std::invoke_result_t<F>>;
846 return expected<U, E>(std::in_place, std::invoke(std::forward<F>(f)));
847 return expected<U, E>(unexpect, std::move(error_));
850 template <
typename F>
851 constexpr auto transform_error(F&& f) &
853 using G = std::remove_cv_t<std::invoke_result_t<F, E&>>;
855 return expected<void, G>();
856 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
859 template <
typename F>
860 constexpr auto transform_error(F&& f)
const&
862 using G = std::remove_cv_t<std::invoke_result_t<F, E const&>>;
864 return expected<void, G>();
865 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), error_));
868 template <
typename F>
869 constexpr auto transform_error(F&& f) &&
871 using G = std::remove_cv_t<std::invoke_result_t<F, E&&>>;
873 return expected<void, G>();
874 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
877 template <
typename F>
878 constexpr auto transform_error(F&& f)
const&&
880 using G = std::remove_cv_t<std::invoke_result_t<F, E const&&>>;
882 return expected<void, G>();
883 return expected<void, G>(unexpect, std::invoke(std::forward<F>(f), std::move(error_)));
887 template <
typename E2>
888 constexpr friend auto operator==(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
890 if (lhs.has_value() != rhs.has_value())
894 return lhs.error() == rhs.error();
897 template <
typename E2>
898 constexpr friend auto operator!=(expected
const& lhs, expected<void, E2>
const& rhs) ->
bool
900 return !(lhs == rhs);
903 template <
typename E2>
904 constexpr friend auto operator==(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
906 return !lhs.has_value() && lhs.error() == rhs.error();
909 template <
typename E2>
910 constexpr friend auto operator==(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
912 return !rhs.has_value() && lhs.error() == rhs.error();
915 template <
typename E2>
916 constexpr friend auto operator!=(expected
const& lhs,
unexpected<E2> const& rhs) ->
bool
918 return !(lhs == rhs);
921 template <
typename E2>
922 constexpr friend auto operator!=(
unexpected<E2> const& lhs, expected
const& rhs) ->
bool
924 return !(lhs == rhs);