32 #ifndef RESULT_RESULT_HPP
33 #define RESULT_RESULT_HPP
36 #include <type_traits>
41 #include <initializer_list>
44 #if defined(RESULT_EXCEPTIONS_DISABLED)
50 #if __cplusplus
>= 201402L
51 # define RESULT_CPP14_CONSTEXPR constexpr
53 # define RESULT_CPP14_CONSTEXPR
56 #if __cplusplus
>= 201703L
57 # define RESULT_CPP17_INLINE inline
59 # define RESULT_CPP17_INLINE
62 #if defined(__clang__
) && defined(_MSC_VER)
63 # define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden")))
64 #elif defined(__clang__
) || defined(__GNUC__
)
65 # define RESULT_INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline))
66 #elif defined(_MSC_VER)
67 # define RESULT_INLINE_VISIBILITY __forceinline
69 # define RESULT_INLINE_VISIBILITY
74 #if __cplusplus
>= 201703L
75 # define RESULT_NODISCARD [[nodiscard]]
76 # define RESULT_WARN_UNUSED [[nodiscard]]
77 #elif defined(__clang__
) && ((__clang_major__
> 3
) || ((__clang_major__
== 3
) && (__clang_minor__
>= 9
)))
78 # define RESULT_NODISCARD [[clang::warn_unused_result]]
79 # define RESULT_WARN_UNUSED [[clang::warn_unused_result]]
80 #elif defined(__GNUC__)
81 # define RESULT_NODISCARD
82 # define RESULT_WARN_UNUSED [[gnu::warn_unused_result]]
84 # define RESULT_WARN_UNUSED
85 # define RESULT_NODISCARD
88 #if defined(RESULT_NAMESPACE)
89 # define RESULT_NAMESPACE_INTERNAL RESULT_NAMESPACE
91 # define RESULT_NAMESPACE_INTERNAL cpp
93 #define RESULT_NS_IMPL RESULT_NAMESPACE_INTERNAL::bitwizeshift
97 #if defined(__clang__
)
98 # pragma clang diagnostic push
99 # pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
103 inline namespace bitwizeshift {
111 #if __cplusplus
>= 201402L
114 template <
typename T>
116 auto forward(
typename std::remove_reference<T>::type& t)
119 return static_cast<T&&>(t);
122 template <
typename T>
124 auto forward(
typename std::remove_reference<T>::type&& t)
127 return static_cast<T&&>(t);
140 #if __cplusplus
>= 201703L
142 using std::invoke_result;
143 using std::invoke_result_t;
146 struct is_reference_wrapper : std::false_type{};
149 struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type{};
153 template <
typename Base,
typename T,
typename Derived,
typename... Args,
154 typename =
typename std::enable_if<
155 std::is_function<T>::value &&
156 std::is_base_of<Base,
typename std::decay<Derived>::type>::value
159 auto invoke(T Base::*pmf, Derived&& ref, Args&&... args)
166 template <
typename Base,
typename T,
typename RefWrap,
typename... Args,
167 typename =
typename std::enable_if<
168 std::is_function<T>::value &&
169 is_reference_wrapper<
typename std::decay<RefWrap>::type>::value
172 auto invoke(T Base::*pmf, RefWrap&& ref, Args&&... args)
173 noexcept(
noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
174 ->
decltype((ref.get().*pmf)(
RESULT_NS_IMPL::detail::forward<Args>(args)...))
176 return (ref.get().*pmf)(
RESULT_NS_IMPL::detail::forward<Args>(args)...);
179 template <
typename Base,
typename T,
typename Pointer,
typename... Args,
180 typename =
typename std::enable_if<
181 std::is_function<T>::value &&
182 !is_reference_wrapper<
typename std::decay<Pointer>::type>::value &&
183 !std::is_base_of<Base,
typename std::decay<Pointer>::type>::value
186 auto invoke(T Base::*pmf, Pointer&& ptr, Args&&... args)
187 noexcept(
noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
193 template <
typename Base,
typename T,
typename Derived,
194 typename =
typename std::enable_if<
195 !std::is_function<T>::value &&
196 std::is_base_of<Base,
typename std::decay<Derived>::type>::value
199 auto invoke(T Base::*pmd, Derived&& ref)
200 noexcept(
noexcept(std::forward<Derived>(ref).*pmd))
206 template <
typename Base,
typename T,
typename RefWrap,
207 typename =
typename std::enable_if<
208 !std::is_function<T>::value &&
209 is_reference_wrapper<
typename std::decay<RefWrap>::type>::value
212 auto invoke(T Base::*pmd, RefWrap&& ref)
213 noexcept(
noexcept(ref.get().*pmd))
214 ->
decltype(ref.get().*pmd)
216 return ref.get().*pmd;
219 template <
typename Base,
typename T,
typename Pointer,
220 typename =
typename std::enable_if<
221 !std::is_function<T>::value &&
222 !is_reference_wrapper<
typename std::decay<Pointer>::type>::value &&
223 !std::is_base_of<Base,
typename std::decay<Pointer>::type>::value
226 auto invoke(T Base::*pmd, Pointer&& ptr)
227 noexcept(
noexcept((*std::forward<Pointer>(ptr)).*pmd))
228 ->
decltype((*
RESULT_NS_IMPL::detail::forward<Pointer>(ptr)).*pmd)
233 template <
typename F,
typename... Args,
234 typename =
typename std::enable_if<!std::is_member_pointer<
typename std::decay<F>::type>::value>::type>
236 auto invoke(F&& f, Args&&... args)
237 noexcept(
noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
243 template<
typename Fn,
typename...Args>
246 template <
typename Fn2,
typename...Args2>
247 static auto test( Fn2&&, Args2&&... )
248 ->
decltype(invoke(std::declval<Fn2>(), std::declval<Args2>()...), std::true_type{});
250 static auto test(...)
253 using type =
decltype(test(std::declval<Fn>(), std::declval<Args>()...));
254 static constexpr bool value = type::value;
257 template <
bool B,
typename Fn,
typename...Args>
258 struct invoke_result_impl {
259 using type =
decltype(
RESULT_NS_IMPL::detail::invoke(std::declval<Fn>(), std::declval<Args>()...));
261 template <
typename Fn,
typename...Args>
262 struct invoke_result_impl<
false, Fn, Args...>{};
264 template <
typename Fn,
typename...Args>
266 : invoke_result_impl<is_invocable<Fn,Args...>::value, Fn, Args...>{};
268 template <
typename Fn,
typename...Args>
269 using invoke_result_t =
typename invoke_result<Fn, Args...>::type;
277 #if __cplusplus
>= 201703L
278 using std::in_place_t;
284 explicit in_place_t() =
default;
296 explicit in_place_error_t() =
default;
308 template <
typename,
typename>
312 class bad_result_access;
318 template <
typename T>
320 template <
typename E>
323 template <
typename T>
325 template <
typename T,
typename E>
334 template <
typename T>
335 using wrapped_result_type =
typename std::conditional<
336 std::is_lvalue_reference<T>::value,
337 std::reference_wrapper<
338 typename std::remove_reference<T>::type
340 typename std::remove_const<T>::type
345 #if !defined(RESULT_DISABLE_EXCEPTIONS)
355 template <
typename E>
356 class bad_result_access :
public std::logic_error
367 template <
typename E2,
368 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
377 template <
typename E2,
378 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
380 template <
typename E2,
381 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
385 bad_result_access(
const bad_result_access& other) =
default;
386 bad_result_access(bad_result_access&& other) =
default;
390 auto operator=(
const bad_result_access& other) -> bad_result_access& =
default;
391 auto operator=(bad_result_access&& other) -> bad_result_access& =
default;
397 auto error() &
noexcept -> E&;
398 auto error() &&
noexcept -> E&&;
399 auto error()
const &
noexcept ->
const E&;
400 auto error()
const &&
noexcept ->
const E&&;
415 template <
typename E,
typename E2>
416 using failure_is_value_convertible = std::integral_constant<
bool,(
417 std::is_constructible<E, E2&&>::value &&
418 !std::is_same<
typename std::decay<E2>::type,
in_place_t>::value &&
419 !
is_failure<
typename std::decay<E2>::type>::value &&
420 !
is_result<
typename std::decay<E2>::type>::value
423 template <
typename E,
typename E2>
424 using failure_is_explicit_value_convertible = std::integral_constant<
bool,(
425 failure_is_value_convertible<E, E2>::value &&
426 !std::is_convertible<E2, E>::value
429 template <
typename E,
typename E2>
430 using failure_is_implicit_value_convertible = std::integral_constant<
bool,(
431 failure_is_value_convertible<E, E2>::value &&
432 std::is_convertible<E2, E>::value
435 template <
typename E,
typename E2>
436 using failure_is_value_assignable = std::integral_constant<
bool,(
437 !
is_result<
typename std::decay<E2>::type>::value &&
438 !
is_failure<
typename std::decay<E2>::type>::value &&
439 std::is_assignable<wrapped_result_type<E>&,E2>::value
454 template <
typename E>
458 !
is_result<
typename std::decay<E>::type>::value,
459 "A (possibly CV-qualified) result 'E' type is ill-formed."
462 !
is_failure<
typename std::decay<E>::type>::value,
463 "A (possibly CV-qualified) failure 'E' type is ill-formed."
466 !std::is_void<
typename std::decay<E>::type>::value,
467 "A (possibly CV-qualified) 'void' 'E' type is ill-formed."
470 !std::is_rvalue_reference<E>::value,
471 "rvalue references for 'E' type is ill-formed. "
472 "Only lvalue references are valid."
480 using error_type = E;
494 template <
typename...Args,
495 typename =
typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
504 template <
typename U,
typename...Args,
505 typename =
typename std::enable_if<std::is_constructible<E,std::initializer_list<U>,Args...>::value>::type>
513 template <
typename E2,
514 typename std::enable_if<detail::failure_is_implicit_value_convertible<E,E2>::value,
int>::type = 0>
517 template <
typename E2,
518 typename std::enable_if<detail::failure_is_explicit_value_convertible<E,E2>::value,
int>::type = 0>
519 constexpr explicit failure(E2&& error)
527 failure(
const failure& other) =
default;
533 failure(failure&& other) =
default;
538 template <
typename E2,
539 typename =
typename std::enable_if<std::is_constructible<E,
const E2&>::value>::type>
540 constexpr failure(
const failure<E2>& other)
546 template <
typename E2,
547 typename =
typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
548 constexpr failure(failure<E2>&& other)
558 template <
typename E2,
559 typename =
typename std::enable_if<detail::failure_is_value_assignable<E,E2>::value>::type>
568 auto operator=(
const failure& other) -> failure& =
default;
574 auto operator=(failure&& other) -> failure& =
default;
580 template <
typename E2,
581 typename =
typename std::enable_if<std::is_assignable<E&,
const E2&>::value>::type>
583 auto operator=(
const failure<E2>& other)
590 template <
typename E2,
591 typename =
typename std::enable_if<std::is_assignable<E&,E2&&>::value>::type>
606 auto error() &
noexcept
607 ->
typename std::add_lvalue_reference<E>::
type;
609 auto error() &&
noexcept
610 ->
typename std::add_rvalue_reference<E>::
type;
611 constexpr auto error()
const &
noexcept
612 ->
typename std::add_lvalue_reference<
typename std::add_const<E>::
type>::
type;
613 constexpr auto error()
const &&
noexcept
614 ->
typename std::add_rvalue_reference<
typename std::add_const<E>::
type>::
type;
622 using underlying_type = detail::wrapped_result_type<E>;
629 underlying_type m_failure;
632 #if __cplusplus
>= 201703L
633 template <
typename T>
634 failure(std::reference_wrapper<T>) -> failure<T&>;
636 template <
typename T>
637 failure(T&&) -> failure<
typename std::decay<T>::type>;
648 template <
typename E1,
typename E2>
649 constexpr auto operator==(
const failure<E1>& lhs,
650 const failure<E2>& rhs)
noexcept ->
bool;
651 template <
typename E1,
typename E2>
652 constexpr auto operator!=(
const failure<E1>& lhs,
653 const failure<E2>& rhs)
noexcept ->
bool;
654 template <
typename E1,
typename E2>
655 constexpr auto operator<(
const failure<E1>& lhs,
656 const failure<E2>& rhs)
noexcept ->
bool;
657 template <
typename E1,
typename E2>
658 constexpr auto operator>(
const failure<E1>& lhs,
659 const failure<E2>& rhs)
noexcept ->
bool;
660 template <
typename E1,
typename E2>
661 constexpr auto operator<=(
const failure<E1>& lhs,
662 const failure<E2>& rhs)
noexcept ->
bool;
663 template <
typename E1,
typename E2>
664 constexpr auto operator>=(
const failure<E1>& lhs,
665 const failure<E2>& rhs)
noexcept ->
bool;
675 template <
typename E>
677 constexpr auto fail(E&& e)
679 -> failure<
typename std::decay<E>::
type>;
685 template <
typename E>
687 constexpr auto fail(std::reference_wrapper<E> e)
688 noexcept -> failure<E&>;
695 template <
typename E,
typename...Args,
696 typename =
typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
698 constexpr auto fail(Args&&...args)
708 template <
typename E,
typename U,
typename...Args,
709 typename =
typename std::enable_if<std::is_constructible<E,std::initializer_list<U>,Args...>::value>::type>
711 constexpr auto fail(std::initializer_list<U> ilist, Args&&...args)
719 template <
typename E>
720 auto swap(failure<E>& lhs, failure<E>& rhs)
721 #if __cplusplus
>= 201703L
741 constexpr auto operator==(unit, unit)
noexcept ->
bool {
return true; }
742 constexpr auto operator!=(unit, unit)
noexcept ->
bool {
return false; }
743 constexpr auto operator<(unit, unit)
noexcept ->
bool {
return false; }
744 constexpr auto operator>(unit, unit)
noexcept ->
bool {
return false; }
745 constexpr auto operator<=(unit, unit)
noexcept ->
bool {
return true; }
746 constexpr auto operator>=(unit, unit)
noexcept ->
bool {
return true; }
763 template <
typename T,
typename E,
764 bool IsTrivial = std::is_trivially_destructible<T>::value &&
765 std::is_trivially_destructible<E>::value>
772 using underlying_value_type = wrapped_result_type<T>;
773 using underlying_error_type = E;
783 result_union(unit)
noexcept;
788 template <
typename...Args>
789 constexpr result_union(
in_place_t, Args&&...args)
790 noexcept(std::is_nothrow_constructible<T, Args...>::value);
795 template <
typename...Args>
797 noexcept(std::is_nothrow_constructible<E, Args...>::value);
799 result_union(
const result_union&) =
default;
800 result_union(result_union&&) =
default;
804 auto operator=(
const result_union&) -> result_union& =
default;
805 auto operator=(result_union&&) -> result_union& =
default;
812 auto destroy()
const noexcept ->
void;
819 underlying_value_type m_value;
820 underlying_error_type m_error;
828 template <
typename T,
typename E>
829 struct result_union<T, E,
false>
835 using underlying_value_type = wrapped_result_type<T>;
836 using underlying_error_type = E;
846 result_union(unit)
noexcept;
851 template <
typename...Args>
852 constexpr result_union(
in_place_t, Args&&...args)
853 noexcept(std::is_nothrow_constructible<T, Args...>::value);
858 template <
typename...Args>
860 noexcept(std::is_nothrow_constructible<E, Args...>::value);
862 result_union(
const result_union&) =
default;
863 result_union(result_union&&) =
default;
869 noexcept(std::is_nothrow_destructible<T>::value &&
870 std::is_nothrow_destructible<E>::value);
874 auto operator=(
const result_union&) -> result_union& =
default;
875 auto operator=(result_union&&) -> result_union& =
default;
882 auto destroy() ->
void;
889 underlying_value_type m_value;
890 underlying_error_type m_error;
914 template <
typename T,
typename E>
915 struct result_construct_base
925 result_construct_base(unit)
noexcept;
930 template <
typename...Args>
931 constexpr result_construct_base(
in_place_t, Args&&...args)
932 noexcept(std::is_nothrow_constructible<T, Args...>::value);
937 template <
typename...Args>
939 noexcept(std::is_nothrow_constructible<E, Args...>::value);
941 result_construct_base(
const result_construct_base&) =
default;
942 result_construct_base(result_construct_base&&) =
default;
944 auto operator=(
const result_construct_base&) -> result_construct_base& =
default;
945 auto operator=(result_construct_base&&) -> result_construct_base& =
default;
959 template <
typename...Args>
960 auto construct_value(Args&&...args)
961 noexcept(std::is_nothrow_constructible<T,Args...>::value) ->
void;
971 template <
typename...Args>
972 auto construct_error(Args&&...args)
973 noexcept(std::is_nothrow_constructible<E,Args...>::value) ->
void;
986 template <
typename Result>
987 auto construct_error_from_result(Result&& other) ->
void;
997 template <
typename Result>
998 auto construct_from_result(Result&& other) ->
void;
1002 template <
typename Value>
1003 auto assign_value(Value&& value)
1004 noexcept(std::is_nothrow_assignable<T, Value>::value) ->
void;
1006 template <
typename Error>
1007 auto assign_error(Error&& error)
1008 noexcept(std::is_nothrow_assignable<E, Error>::value) ->
void;
1010 template <
typename Result>
1011 auto assign_from_result(Result&& other) ->
void;
1015 template <
typename ReferenceWrapper>
1016 auto construct_value_from_result_impl(std::true_type, ReferenceWrapper&& reference)
1019 template <
typename Value>
1020 auto construct_value_from_result_impl(std::false_type, Value&& value)
1021 noexcept(std::is_nothrow_constructible<T,Value>::value) ->
void;
1023 template <
typename Result>
1024 auto assign_value_from_result_impl(std::true_type, Result&& other) ->
void;
1026 template <
typename Result>
1027 auto assign_value_from_result_impl(std::false_type, Result&& other) ->
void;
1033 using storage_type = result_union<T, E>;
1035 storage_type storage;
1042 template <
typename T,
typename E>
1043 struct result_trivial_copy_ctor_base_impl : result_construct_base<T,E>
1045 using base_type = result_construct_base<T,E>;
1046 using base_type::base_type;
1048 result_trivial_copy_ctor_base_impl(
const result_trivial_copy_ctor_base_impl& other)
1049 noexcept(std::is_nothrow_copy_constructible<T>::value &&
1050 std::is_nothrow_copy_constructible<E>::value);
1051 result_trivial_copy_ctor_base_impl(result_trivial_copy_ctor_base_impl&& other) =
default;
1053 auto operator=(
const result_trivial_copy_ctor_base_impl& other) -> result_trivial_copy_ctor_base_impl& =
default;
1054 auto operator=(result_trivial_copy_ctor_base_impl&& other) -> result_trivial_copy_ctor_base_impl& =
default;
1057 template <
bool Condition,
typename Base>
1058 using conditionally_nest_type =
typename std::conditional<
1060 typename Base::base_type,
1064 template <
typename T,
typename E>
1065 using result_trivial_copy_ctor_base = conditionally_nest_type<
1066 std::is_trivially_copy_constructible<T>::value &&
1067 std::is_trivially_copy_constructible<E>::value,
1068 result_trivial_copy_ctor_base_impl<T,E>
1075 template <
typename T,
typename E>
1076 struct result_trivial_move_ctor_base_impl : result_trivial_copy_ctor_base<T,E>
1078 using base_type = result_trivial_copy_ctor_base<T,E>;
1079 using base_type::base_type;
1081 result_trivial_move_ctor_base_impl(
const result_trivial_move_ctor_base_impl& other) =
default;
1082 result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
1083 noexcept(std::is_nothrow_move_constructible<T>::value &&
1084 std::is_nothrow_move_constructible<E>::value);
1086 auto operator=(
const result_trivial_move_ctor_base_impl& other) -> result_trivial_move_ctor_base_impl& =
default;
1087 auto operator=(result_trivial_move_ctor_base_impl&& other) -> result_trivial_move_ctor_base_impl& =
default;
1090 template <
typename T,
typename E>
1091 using result_trivial_move_ctor_base = conditionally_nest_type<
1092 std::is_trivially_move_constructible<T>::value &&
1093 std::is_trivially_move_constructible<E>::value,
1094 result_trivial_move_ctor_base_impl<T,E>
1101 template <
typename T,
typename E>
1102 struct result_trivial_copy_assign_base_impl
1103 : result_trivial_move_ctor_base<T, E>
1105 using base_type = result_trivial_move_ctor_base<T,E>;
1106 using base_type::base_type;
1108 result_trivial_copy_assign_base_impl(
const result_trivial_copy_assign_base_impl& other) =
default;
1109 result_trivial_copy_assign_base_impl(result_trivial_copy_assign_base_impl&& other) =
default;
1111 auto operator=(
const result_trivial_copy_assign_base_impl& other)
1112 noexcept(std::is_nothrow_copy_constructible<T>::value &&
1113 std::is_nothrow_copy_constructible<E>::value &&
1114 std::is_nothrow_copy_assignable<T>::value &&
1115 std::is_nothrow_copy_assignable<E>::value)
1116 -> result_trivial_copy_assign_base_impl&;
1117 auto operator=(result_trivial_copy_assign_base_impl&& other)
1118 -> result_trivial_copy_assign_base_impl& =
default;
1121 template <
typename T,
typename E>
1122 using result_trivial_copy_assign_base = conditionally_nest_type<
1123 std::is_trivially_copy_constructible<T>::value &&
1124 std::is_trivially_copy_constructible<E>::value &&
1125 std::is_trivially_copy_assignable<T>::value &&
1126 std::is_trivially_copy_assignable<E>::value &&
1127 std::is_trivially_destructible<T>::value &&
1128 std::is_trivially_destructible<E>::value,
1129 result_trivial_copy_assign_base_impl<T,E>
1136 template <
typename T,
typename E>
1137 struct result_trivial_move_assign_base_impl
1138 : result_trivial_copy_assign_base<T, E>
1140 using base_type = result_trivial_copy_assign_base<T,E>;
1141 using base_type::base_type;
1143 result_trivial_move_assign_base_impl(
const result_trivial_move_assign_base_impl& other) =
default;
1144 result_trivial_move_assign_base_impl(result_trivial_move_assign_base_impl&& other) =
default;
1146 auto operator=(
const result_trivial_move_assign_base_impl& other)
1147 -> result_trivial_move_assign_base_impl& =
default;
1148 auto operator=(result_trivial_move_assign_base_impl&& other)
1149 noexcept(std::is_nothrow_move_constructible<T>::value &&
1150 std::is_nothrow_move_constructible<E>::value &&
1151 std::is_nothrow_move_assignable<T>::value &&
1152 std::is_nothrow_move_assignable<E>::value)
1153 -> result_trivial_move_assign_base_impl&;
1156 template <
typename T,
typename E>
1157 using result_trivial_move_assign_base = conditionally_nest_type<
1158 std::is_trivially_move_constructible<T>::value &&
1159 std::is_trivially_move_constructible<E>::value &&
1160 std::is_trivially_move_assignable<T>::value &&
1161 std::is_trivially_move_assignable<E>::value &&
1162 std::is_trivially_destructible<T>::value &&
1163 std::is_trivially_destructible<E>::value,
1164 result_trivial_move_assign_base_impl<T,E>
1171 template <
typename T,
typename E>
1172 struct disable_copy_ctor : result_trivial_move_assign_base<T,E>
1174 using base_type = result_trivial_move_assign_base<T,E>;
1175 using base_type::base_type;
1177 disable_copy_ctor(
const disable_copy_ctor& other) =
delete;
1178 disable_copy_ctor(disable_copy_ctor&& other) =
default;
1180 auto operator=(
const disable_copy_ctor& other)
1181 -> disable_copy_ctor& =
default;
1182 auto operator=(disable_copy_ctor&& other)
1183 -> disable_copy_ctor& =
default;
1186 template <
typename T,
typename E>
1187 using result_copy_ctor_base = conditionally_nest_type<
1188 std::is_copy_constructible<T>::value &&
1189 std::is_copy_constructible<E>::value,
1190 disable_copy_ctor<T,E>
1197 template <
typename T,
typename E>
1198 struct disable_move_ctor : result_copy_ctor_base<T,E>
1200 using base_type = result_copy_ctor_base<T,E>;
1201 using base_type::base_type;
1203 disable_move_ctor(
const disable_move_ctor& other) =
default;
1204 disable_move_ctor(disable_move_ctor&& other) =
delete;
1206 auto operator=(
const disable_move_ctor& other)
1207 -> disable_move_ctor& =
default;
1208 auto operator=(disable_move_ctor&& other)
1209 -> disable_move_ctor& =
default;
1212 template <
typename T,
typename E>
1213 using result_move_ctor_base = conditionally_nest_type<
1214 std::is_move_constructible<T>::value &&
1215 std::is_move_constructible<E>::value,
1216 disable_move_ctor<T,E>
1223 template <
typename T,
typename E>
1224 struct disable_move_assignment
1225 : result_move_ctor_base<T, E>
1227 using base_type = result_move_ctor_base<T, E>;
1228 using base_type::base_type;
1230 disable_move_assignment(
const disable_move_assignment& other) =
default;
1231 disable_move_assignment(disable_move_assignment&& other) =
default;
1233 auto operator=(
const disable_move_assignment& other)
1234 -> disable_move_assignment& =
delete;
1235 auto operator=(disable_move_assignment&& other)
1236 -> disable_move_assignment& =
default;
1239 template <
typename T,
typename E>
1240 using result_copy_assign_base = conditionally_nest_type<
1241 std::is_nothrow_copy_constructible<T>::value &&
1242 std::is_nothrow_copy_constructible<E>::value &&
1243 std::is_copy_assignable<wrapped_result_type<T>>::value &&
1244 std::is_copy_assignable<E>::value,
1245 disable_move_assignment<T,E>
1252 template <
typename T,
typename E>
1253 struct disable_copy_assignment
1254 : result_copy_assign_base<T, E>
1256 using base_type = result_copy_assign_base<T, E>;
1257 using base_type::base_type;
1259 disable_copy_assignment(
const disable_copy_assignment& other) =
default;
1260 disable_copy_assignment(disable_copy_assignment&& other) =
default;
1262 auto operator=(
const disable_copy_assignment& other)
1263 -> disable_copy_assignment& =
default;
1264 auto operator=(disable_copy_assignment&& other)
1265 -> disable_copy_assignment& =
delete;
1268 template <
typename T,
typename E>
1269 using result_move_assign_base = conditionally_nest_type<
1270 std::is_nothrow_move_constructible<T>::value &&
1271 std::is_nothrow_move_constructible<E>::value &&
1272 std::is_move_assignable<wrapped_result_type<T>>::value &&
1273 std::is_move_assignable<E>::value,
1274 disable_copy_assignment<T,E>
1281 template <
typename T,
typename E>
1282 using result_storage = result_move_assign_base<T, E>;
1288 template <
typename T1,
typename E1,
typename T2,
typename E2>
1289 using result_is_convertible = std::integral_constant<
bool,(
1291 std::is_constructible<T1, result<T2,E2>&>:: value ||
1292 std::is_constructible<T1,
const result<T2,E2>&>:: value ||
1293 std::is_constructible<T1, result<T2,E2>&&>:: value ||
1294 std::is_constructible<T1,
const result<T2,E2>&&>:: value ||
1297 std::is_constructible<E1, result<T2,E2>&>:: value ||
1298 std::is_constructible<E1,
const result<T2,E2>&>:: value ||
1299 std::is_constructible<E1, result<T2,E2>&&>:: value ||
1300 std::is_constructible<E1,
const result<T2,E2>&&>:: value ||
1303 std::is_convertible<result<T2,E2>&, T1>:: value ||
1304 std::is_convertible<
const result<T2,E2>&, T1>:: value ||
1305 std::is_convertible<result<T2,E2>&&, T1>::value ||
1306 std::is_convertible<
const result<T2,E2>&&, T1>::value ||
1309 std::is_convertible<result<T2,E2>&, E1>:: value ||
1310 std::is_convertible<
const result<T2,E2>&, E1>:: value ||
1311 std::is_convertible<result<T2,E2>&&, E1>::value ||
1312 std::is_convertible<
const result<T2,E2>&&, E1>::value
1317 template <
typename T1,
typename E1,
typename T2,
typename E2>
1318 using result_is_copy_convertible = std::integral_constant<
bool,(
1319 !result_is_convertible<T1,E1,T2,E2>::value &&
1320 std::is_constructible<T1,
const T2&>::value &&
1321 std::is_constructible<E1,
const E2&>::value
1324 template <
typename T1,
typename E1,
typename T2,
typename E2>
1325 using result_is_implicit_copy_convertible = std::integral_constant<
bool,(
1326 result_is_copy_convertible<T1,E1,T2,E2>::value &&
1327 std::is_convertible<
const T2&, T1>::value &&
1328 std::is_convertible<
const E2&, E1>::value
1331 template <
typename T1,
typename E1,
typename T2,
typename E2>
1332 using result_is_explicit_copy_convertible = std::integral_constant<
bool,(
1333 result_is_copy_convertible<T1,E1,T2,E2>::value &&
1334 (!std::is_convertible<
const T2&, T1>::value ||
1335 !std::is_convertible<
const E2&, E1>::value)
1340 template <
typename T1,
typename E1,
typename T2,
typename E2>
1341 using result_is_move_convertible = std::integral_constant<
bool,(
1342 !result_is_convertible<T1,E1,T2,E2>::value &&
1343 std::is_constructible<T1, T2&&>::value &&
1344 std::is_constructible<E1, E2&&>::value
1347 template <
typename T1,
typename E1,
typename T2,
typename E2>
1348 using result_is_implicit_move_convertible = std::integral_constant<
bool,(
1349 result_is_move_convertible<T1,E1,T2,E2>::value &&
1350 std::is_convertible<T2&&, T1>::value &&
1351 std::is_convertible<E2&&, E1>::value
1354 template <
typename T1,
typename E1,
typename T2,
typename E2>
1355 using result_is_explicit_move_convertible = std::integral_constant<
bool,(
1356 result_is_move_convertible<T1,E1,T2,E2>::value &&
1357 (!std::is_convertible<T2&&, T1>::value ||
1358 !std::is_convertible<E2&&, E1>::value)
1363 template <
typename T,
typename U>
1364 using result_is_value_convertible = std::integral_constant<
bool,(
1365 std::is_constructible<T, U&&>::value &&
1366 !std::is_same<
typename std::decay<U>::type,
in_place_t>::value &&
1368 !
is_result<
typename std::decay<U>::type>::value
1371 template <
typename T,
typename U>
1372 using result_is_explicit_value_convertible = std::integral_constant<
bool,(
1373 result_is_value_convertible<T, U>::value &&
1374 !std::is_convertible<U&&, T>::value
1377 template <
typename T,
typename U>
1378 using result_is_implicit_value_convertible = std::integral_constant<
bool,(
1379 result_is_value_convertible<T, U>::value &&
1380 std::is_convertible<U&&, T>::value
1385 template <
typename T1,
typename E1,
typename T2,
typename E2>
1386 using result_is_convert_assignable = std::integral_constant<
bool,(
1387 result_is_convertible<T1,E1,T2,E2>::value &&
1389 std::is_assignable<T1&, result<T2,E2>&>::value &&
1390 std::is_assignable<T1&,
const result<T2,E2>&>::value &&
1391 std::is_assignable<T1&, result<T2,E2>&&>::value &&
1392 std::is_assignable<T1&,
const result<T2,E2>&&>::value &&
1394 std::is_assignable<E1&, result<T2,E2>&>::value &&
1395 std::is_assignable<E1&,
const result<T2,E2>&>::value &&
1396 std::is_assignable<E1&, result<T2,E2>&&>::value &&
1397 std::is_assignable<E1&,
const result<T2,E2>&&>::value
1400 template <
typename T1,
typename E1,
typename T2,
typename E2>
1401 using result_is_copy_convert_assignable = std::integral_constant<
bool,(
1402 !result_is_convert_assignable<T1,E1,T2,E2>::value &&
1404 std::is_nothrow_constructible<T1,
const T2&>::value &&
1405 std::is_assignable<wrapped_result_type<T1>&,
const T2&>::value &&
1406 std::is_nothrow_constructible<E1,
const E2&>::value &&
1407 std::is_assignable<E1&,
const E2&>::value
1410 template <
typename T1,
typename E1,
typename T2,
typename E2>
1411 using result_is_move_convert_assignable = std::integral_constant<
bool,(
1412 !result_is_convert_assignable<T1,E1,T2,E2>::value &&
1414 std::is_nothrow_constructible<T1, T2&&>::value &&
1415 std::is_assignable<T1&, T2&&>::value &&
1416 std::is_nothrow_constructible<E1, E2&&>::value &&
1417 std::is_assignable<E1&, E2&&>::value
1422 template <
typename T,
typename U>
1423 using result_is_value_assignable = std::integral_constant<
bool,(
1424 !
is_result<
typename std::decay<U>::type>::value &&
1425 !
is_failure<
typename std::decay<U>::type>::value &&
1426 std::is_nothrow_constructible<T,U>::value &&
1427 std::is_assignable<wrapped_result_type<T>&,U>::value &&
1429 !std::is_same<
typename std::decay<U>::type,
typename std::decay<T>::type>::value ||
1430 !std::is_scalar<T>::value
1434 template <
typename E,
typename E2>
1435 using result_is_failure_assignable = std::integral_constant<
bool,(
1436 std::is_nothrow_constructible<E,E2>::value &&
1437 std::is_assignable<E&,E2>::value
1444 struct result_error_extractor
1446 template <
typename T,
typename E>
1447 static constexpr auto get(
const result<T,E>& exp)
noexcept ->
const E&;
1448 template <
typename T,
typename E>
1449 static constexpr auto get(result<T,E>& exp)
noexcept -> E&;
1452 template <
typename T,
typename E>
1453 constexpr auto extract_error(
const result<T,E>& exp)
noexcept ->
const E&;
1455 template <
typename E>
1457 auto throw_bad_result_access(E&& error) ->
void;
1459 template <
typename String,
typename E>
1461 auto throw_bad_result_access_message(String&& message, E&& error) ->
void;
1533 template <
typename T,
typename E>
1539 !std::is_abstract<T>::value,
1540 "It is ill-formed for T to be abstract type"
1543 !std::is_same<
typename std::decay<T>::type,
in_place_t>::value,
1544 "It is ill-formed for T to be a (possibly CV-qualified) in_place_t type"
1547 !
is_result<
typename std::decay<T>::type>::value,
1548 "It is ill-formed for T to be a (possibly CV-qualified) 'result' type"
1551 !
is_failure<
typename std::decay<T>::type>::value,
1552 "It is ill-formed for T to be a (possibly CV-qualified) 'failure' type"
1555 !std::is_rvalue_reference<T>::value,
1556 "It is ill-formed for T to be an rvalue 'result type. "
1557 "Only lvalue references are valid."
1561 !std::is_abstract<E>::value,
1562 "It is ill-formed for E to be abstract type"
1565 !std::is_void<
typename std::decay<E>::type>::value,
1566 "It is ill-formed for E to be (possibly CV-qualified) void type"
1569 !
is_result<
typename std::decay<E>::type>::value,
1570 "It is ill-formed for E to be a (possibly CV-qualified) 'result' type"
1573 !
is_failure<
typename std::decay<E>::type>::value,
1574 "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type"
1577 !std::is_same<
typename std::decay<E>::type,
in_place_t>::value,
1578 "It is ill-formed for E to be a (possibly CV-qualified) in_place_t type"
1581 !std::is_reference<E>::value,
1582 "It is ill-formed for E to be a reference type. "
1583 "Only T types may be lvalue references"
1588 friend detail::result_error_extractor;
1590 template <
typename T2,
typename E2>
1591 friend class result;
1598 using value_type = T;
1599 using error_type = E;
1600 using failure_type = failure<E>;
1602 template <
typename U>
1603 using rebind = result<U,E>;
1622 template <
typename U=T,
1623 typename =
typename std::enable_if<std::is_constructible<U>::value>::type>
1656 constexpr result(
const result& other) =
default;
1689 constexpr result(result&& other) =
default;
1727 template <
typename T2,
typename E2,
1728 typename std::enable_if<detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,
int>::type = 0>
1729 result(
const result<T2,E2>& other)
1732 template <
typename T2,
typename E2,
1733 typename std::enable_if<detail::result_is_explicit_copy_convertible<T,E,T2,E2>::value,
int>::type = 0>
1734 explicit result(
const result<T2,E2>& other)
1777 template <
typename T2,
typename E2,
1778 typename std::enable_if<detail::result_is_implicit_move_convertible<T,E,T2,E2>::value,
int>::type = 0>
1779 result(result<T2,E2>&& other)
1782 template <
typename T2,
typename E2,
1783 typename std::enable_if<detail::result_is_explicit_move_convertible<T,E,T2,E2>::value,
int>::type = 0>
1784 explicit result(result<T2,E2>&& other)
1808 template <
typename...Args,
1809 typename =
typename std::enable_if<std::is_constructible<T,Args...>::value>::type>
1832 template <
typename U,
typename...Args,
1833 typename =
typename std::enable_if<std::is_constructible<T, std::initializer_list<U>&, Args...>::value>::type>
1835 std::initializer_list<U> ilist,
1858 template <
typename...Args,
1859 typename =
typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
1882 template <
typename U,
typename...Args,
1883 typename =
typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
1885 std::initializer_list<U> ilist,
1910 template <
typename E2,
1911 typename =
typename std::enable_if<std::is_constructible<E,
const E2&>::value>::type>
1912 constexpr result(
const failure<E2>& e)
1914 template <
typename E2,
1915 typename =
typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
1916 constexpr result(failure<E2>&& e)
1951 template <
typename U,
1952 typename std::enable_if<detail::result_is_explicit_value_convertible<T,U>::value,
int>::type = 0>
1953 constexpr explicit result(U&& value)
1955 template <
typename U,
1956 typename std::enable_if<detail::result_is_implicit_value_convertible<T,U>::value,
int>::type = 0>
1957 constexpr result(U&& value)
1981 auto operator=(
const result& other) -> result& =
default;
2002 auto operator=(result&& other) -> result& =
default;
2030 template <
typename T2,
typename E2,
2031 typename =
typename std::enable_if<detail::result_is_copy_convert_assignable<T,E,T2,E2>::value>::type>
2032 auto operator=(
const result<T2,E2>& other)
2062 template <
typename T2,
typename E2,
2063 typename =
typename std::enable_if<detail::result_is_move_convert_assignable<T,E,T2,E2>::value>::type>
2064 auto operator=(result<T2,E2>&& other)
2085 template <
typename U,
2086 typename =
typename std::enable_if<detail::result_is_value_assignable<T,U>::value>::type>
2103 template <
typename E2,
2104 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,
const E2&>::value>::type>
2105 auto operator=(
const failure<E2>& other)
2107 template <
typename E2,
2108 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
2109 auto operator=(failure<E2>&& other)
2144 noexcept ->
typename std::remove_reference<T>::
type*;
2147 const noexcept ->
typename std::remove_reference<
typename std::add_const<T>::
type>::
type*;
2178 &
noexcept ->
typename std::add_lvalue_reference<T>::
type;
2181 &&
noexcept ->
typename std::add_rvalue_reference<T>::type;
2183 constexpr auto operator*()
2184 const&
noexcept ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type;
2186 constexpr auto operator*()
2187 const&&
noexcept ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
2214 constexpr explicit operator
bool()
const noexcept;
2235 constexpr auto has_value()
const noexcept ->
bool;
2257 constexpr auto has_error()
const noexcept ->
bool;
2297 & ->
typename std::add_lvalue_reference<T>::
type;
2300 && ->
typename std::add_rvalue_reference<T>::type;
2302 constexpr auto value()
2303 const & ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type;
2305 constexpr auto value()
2306 const && ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
2347 constexpr auto error()
const &
2352 noexcept(std::is_nothrow_constructible<E>::value &&
2353 std::is_nothrow_move_constructible<E>::value) -> E;
2382 template <
typename String,
2383 typename =
typename std::enable_if<(
2384 std::is_convertible<String,
const std::string&>::value &&
2385 std::is_copy_constructible<E>::value
2388 template <
typename String,
2389 typename =
typename std::enable_if<(
2390 std::is_convertible<String,
const std::string&>::value &&
2391 std::is_move_constructible<E>::value
2394 template <
typename String,
2395 typename =
typename std::enable_if<(
2396 std::is_convertible<String,
const std::string&>::value &&
2397 std::is_copy_constructible<E>::value
2399 RESULT_CPP14_CONSTEXPR auto expect(String&& message)
const & ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type;
2400 template <
typename String,
2401 typename =
typename std::enable_if<(
2402 std::is_convertible<String,
const std::string&>::value &&
2403 std::is_copy_constructible<E>::value
2405 RESULT_CPP14_CONSTEXPR auto expect(String&& message)
const && ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
2431 template <
typename U>
2433 constexpr auto value_or(U&& default_value)
2434 const & ->
typename std::remove_reference<T>::
type;
2435 template <
typename U>
2438 && ->
typename std::remove_reference<T>::type;
2459 template <
typename U>
2461 constexpr auto error_or(U&& default_error)
const & -> error_type;
2462 template <
typename U>
2487 template <
typename U>
2489 constexpr auto and_then(U&& value)
const -> result<
typename std::decay<U>::type,E>;
2518 template <
typename Fn>
2520 constexpr auto flat_map(Fn&& fn)
const & -> detail::invoke_result_t<Fn,
const T&>;
2521 template <
typename Fn>
2552 template <
typename Fn>
2554 constexpr auto map(Fn&& fn)
const & -> result<detail::invoke_result_t<Fn,
const T&>,E>;
2555 template <
typename Fn>
2589 template <
typename Fn>
2591 constexpr auto map_error(Fn&& fn)
2592 const & -> result<T, detail::invoke_result_t<Fn,
const E&>>;
2593 template <
typename Fn>
2596 && -> result<T, detail::invoke_result_t<Fn,E&&>>;
2626 template <
typename Fn>
2628 constexpr auto flat_map_error(Fn&& fn)
2629 const & -> detail::invoke_result_t<Fn,
const E&>;
2630 template <
typename Fn>
2633 && -> detail::invoke_result_t<Fn, E&&>;
2641 detail::result_storage<T,E> m_storage;
2652 template <
typename Fn>
2653 constexpr auto map_impl(std::true_type, Fn&& fn)
const & -> result<
void,E>;
2654 template <
typename Fn>
2655 constexpr auto map_impl(std::false_type, Fn&& fn)
const & -> result<detail::invoke_result_t<Fn,
const T&>,E>;
2656 template <
typename Fn>
2658 template <
typename Fn>
2659 RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2672 template <
typename E>
2678 !std::is_void<
typename std::decay<E>::type>::value,
2679 "It is ill-formed for E to be (possibly CV-qualified) void type"
2682 !std::is_abstract<E>::value,
2683 "It is ill-formed for E to be abstract type"
2686 !
is_failure<
typename std::decay<E>::type>::value,
2687 "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type"
2690 !std::is_reference<E>::value,
2691 "It is ill-formed for E to be a reference type. "
2692 "Only T types may be lvalue references"
2697 friend detail::result_error_extractor;
2699 template <
typename T2,
typename E2>
2700 friend class result;
2707 using value_type =
void;
2708 using error_type = E;
2709 using failure_type = failure<E>;
2711 template <
typename U>
2712 using rebind = result<U,E>;
2728 constexpr result()
noexcept;
2751 constexpr result(
const result& other) =
default;
2774 constexpr result(result&& other) =
default;
2799 template <
typename U,
typename E2,
2800 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2801 explicit result(
const result<U,E2>& other)
2826 template <
typename U,
typename E2,
2827 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2828 explicit result(result<U,E2>&& other)
2865 template <
typename...Args,
2866 typename =
typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
2889 template <
typename U,
typename...Args,
2890 typename =
typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
2892 std::initializer_list<U> ilist,
2917 template <
typename E2,
2918 typename =
typename std::enable_if<std::is_constructible<E,
const E2&>::value>::type>
2919 constexpr result(
const failure<E2>& e)
2921 template <
typename E2,
2922 typename =
typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
2923 constexpr result(failure<E2>&& e)
2943 auto operator=(
const result& other) -> result& =
default;
2959 auto operator=(result&& other) -> result& =
default;
2978 template <
typename E2,
2979 typename =
typename std::enable_if<std::is_nothrow_constructible<E,
const E2&>::value &&
2980 std::is_assignable<E&,
const E2&>::value>::type>
2981 auto operator=(
const result<
void,E2>& other)
3001 template <
typename E2,
3002 typename =
typename std::enable_if<std::is_nothrow_constructible<E,E2&&>::value &&
3003 std::is_assignable<E&,E2&&>::value>::type>
3004 auto operator=(result<
void,E2>&& other)
3020 template <
typename E2,
3021 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,
const E2&>::value>::type>
3022 auto operator=(
const failure<E2>& other)
3024 template <
typename E2,
3025 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
3026 auto operator=(failure<E2>&& other)
3059 constexpr explicit operator bool()
const noexcept;
3063 constexpr auto has_value()
const noexcept ->
bool;
3067 constexpr auto has_error()
const noexcept ->
bool;
3108 constexpr auto error()
const &
3119 template <
typename String,
3120 typename =
typename std::enable_if<(
3121 std::is_convertible<String,
const std::string&>::value &&
3122 std::is_copy_constructible<E>::value
3125 template <
typename String,
3126 typename =
typename std::enable_if<(
3127 std::is_convertible<String,
const std::string&>::value &&
3128 std::is_move_constructible<E>::value
3140 template <
typename U>
3142 constexpr auto error_or(U&& default_error)
const & -> error_type;
3143 template <
typename U>
3151 template <
typename U>
3153 constexpr auto and_then(U&& value)
const -> result<
typename std::decay<U>::
type,E>;
3181 template <
typename Fn>
3183 constexpr auto flat_map(Fn&& fn)
const & -> detail::invoke_result_t<Fn>;
3184 template <
typename Fn>
3214 template <
typename Fn>
3216 constexpr auto map(Fn&& fn)
const & -> result<detail::invoke_result_t<Fn>,E>;
3217 template <
typename Fn>
3224 template <
typename Fn>
3225 constexpr auto map_error(Fn&& fn)
const & -> result<
void, detail::invoke_result_t<Fn,
const E&>>;
3226 template <
typename Fn>
3228 auto map_error(Fn&& fn) && -> result<
void, detail::invoke_result_t<Fn,E&&>>;
3234 template <
typename Fn>
3236 constexpr auto flat_map_error(Fn&& fn)
const & -> detail::invoke_result_t<Fn,
const E&>;
3237 template <
typename Fn>
3247 detail::result_storage<detail::unit,E> m_storage;
3258 template <
typename Fn>
3259 constexpr auto map_impl(std::true_type, Fn&& fn)
const & -> result<
void,E>;
3260 template <
typename Fn>
3261 constexpr auto map_impl(std::false_type, Fn&& fn)
const & -> result<detail::invoke_result_t<Fn>,E>;
3262 template <
typename Fn>
3264 template <
typename Fn>
3265 RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3277 template <
typename T1,
typename E1,
typename T2,
typename E2>
3278 constexpr auto operator==(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3280 template <
typename T1,
typename E1,
typename T2,
typename E2>
3281 constexpr auto operator!=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3283 template <
typename T1,
typename E1,
typename T2,
typename E2>
3284 constexpr auto operator>=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3286 template <
typename T1,
typename E1,
typename T2,
typename E2>
3287 constexpr auto operator<=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3289 template <
typename T1,
typename E1,
typename T2,
typename E2>
3290 constexpr auto operator>(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3292 template <
typename T1,
typename E1,
typename T2,
typename E2>
3293 constexpr auto operator<(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3298 template <
typename E1,
typename E2>
3299 constexpr auto operator==(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3301 template <
typename E1,
typename E2>
3302 constexpr auto operator!=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3304 template <
typename E1,
typename E2>
3305 constexpr auto operator>=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3307 template <
typename E1,
typename E2>
3308 constexpr auto operator<=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3310 template <
typename E1,
typename E2>
3311 constexpr auto operator>(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3313 template <
typename E1,
typename E2>
3314 constexpr auto operator<(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3319 template <
typename T,
typename E,
typename U,
3320 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3321 constexpr auto operator==(
const result<T,E>& exp,
const U& value)
3323 template <
typename T,
typename U,
typename E,
3324 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3325 constexpr auto operator==(
const T& value,
const result<U,E>& exp)
3327 template <
typename T,
typename E,
typename U,
3328 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3329 constexpr auto operator!=(
const result<T,E>& exp,
const U& value)
3331 template <
typename T,
typename U,
typename E,
3332 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3333 constexpr auto operator!=(
const T& value,
const result<U,E>& exp)
3335 template <
typename T,
typename E,
typename U,
3336 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3337 constexpr auto operator<=(
const result<T,E>& exp,
const U& value)
3339 template <
typename T,
typename U,
typename E,
3340 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3341 constexpr auto operator<=(
const T& value,
const result<U,E>& exp)
3343 template <
typename T,
typename E,
typename U,
3344 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3345 constexpr auto operator>=(
const result<T,E>& exp,
const U& value)
3347 template <
typename T,
typename U,
typename E,
3348 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3349 constexpr auto operator>=(
const T& value,
const result<U,E>& exp)
3351 template <
typename T,
typename E,
typename U,
3352 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3353 constexpr auto operator<(
const result<T,E>& exp,
const U& value)
3355 template <
typename T,
typename U,
typename E,
3356 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3357 constexpr auto operator<(
const T& value,
const result<U,E>& exp)
3359 template <
typename T,
typename E,
typename U,
3360 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3361 constexpr auto operator>(
const result<T,E>& exp,
const U& value)
3363 template <
typename T,
typename U,
typename E,
3364 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3365 constexpr auto operator>(
const T& value,
const result<U,E>& exp)
3370 template <
typename T,
typename E,
typename U>
3371 constexpr auto operator==(
const result<T,E>& exp,
const failure<U>& value)
3373 template <
typename T,
typename U,
typename E>
3374 constexpr auto operator==(
const failure<T>& value,
const result<E,U>& exp)
3376 template <
typename T,
typename E,
typename U>
3377 constexpr auto operator!=(
const result<T,E>& exp,
const failure<U>& value)
3379 template <
typename T,
typename U,
typename E>
3380 constexpr auto operator!=(
const failure<T>& value,
const result<E,U>& exp)
3382 template <
typename T,
typename E,
typename U>
3383 constexpr auto operator<=(
const result<T,E>& exp,
const failure<U>& value)
3385 template <
typename T,
typename U,
typename E>
3386 constexpr auto operator<=(
const failure<T>& value,
const result<E,U>& exp)
3388 template <
typename T,
typename E,
typename U>
3389 constexpr auto operator>=(
const result<T,E>& exp,
const failure<U>& value)
3391 template <
typename T,
typename U,
typename E>
3392 constexpr auto operator>=(
const failure<T>& value,
const result<E,U>& exp)
3394 template <
typename T,
typename E,
typename U>
3395 constexpr auto operator<(
const result<T,E>& exp,
const failure<U>& value)
3397 template <
typename T,
typename U,
typename E>
3398 constexpr auto operator<(
const failure<T>& value,
const result<E,U>& exp)
3400 template <
typename T,
typename E,
typename U>
3401 constexpr auto operator>(
const result<T,E>& exp,
const failure<U>& value)
3403 template <
typename T,
typename U,
typename E>
3404 constexpr auto operator>(
const failure<T>& value,
const result<E,U>& exp)
3416 template <
typename T,
typename E>
3417 auto swap(result<T,E>& lhs, result<T,E>& rhs)
3418 #if __cplusplus
>= 201703L
3428 template <
typename E>
3429 auto swap(result<
void,E>& lhs, result<
void,E>& rhs)
3430 #if __cplusplus
>= 201703L
3446 template <
typename T,
typename E>
3449 auto operator()(
const RESULT_NS_IMPL::result<T,E>& x)
const -> std::size_t
3451 if (x.has_value()) {
3452 return std::hash<T>{}(*x) + 1;
3454 return std::hash<E>{}(::
RESULT_NS_IMPL::detail::extract_error(x));
3458 template <
typename E>
3461 auto operator()(
const RESULT_NS_IMPL::result<
void,E>& x)
const -> std::size_t
3463 if (x.has_value()) {
3466 return std::hash<E>{}(::
RESULT_NS_IMPL::detail::extract_error(x));
3472 #if !defined(RESULT_DISABLE_EXCEPTIONS)
3482 template <
typename E>
3483 template <
typename E2,
typename>
3486 : logic_error{
"error attempting to access value from result containing error"},
3487 m_error(detail::forward<E2>(error))
3492 template <
typename E>
3493 template <
typename E2,
typename>
3496 const char* what_arg,
3498 ) : logic_error{what_arg},
3499 m_error(detail::forward<E2>(error))
3504 template <
typename E>
3505 template <
typename E2,
typename>
3508 const std::string& what_arg,
3510 ) : logic_error{what_arg},
3511 m_error(detail::forward<E2>(error))
3520 template <
typename E>
3528 template <
typename E>
3533 return static_cast<E&&>(m_error);
3536 template <
typename E>
3539 const &
noexcept ->
const E&
3544 template <
typename E>
3547 const &&
noexcept ->
const E&&
3549 return static_cast<
const E&&>(m_error);
3562 template <
typename E>
3563 template <
typename...Args,
typename>
3567 : m_failure(detail::forward<Args>(args)...)
3572 template <
typename E>
3573 template <
typename U,
typename...Args,
typename>
3577 std::initializer_list<U> ilist,
3580 : m_failure(ilist, detail::forward<Args>(args)...)
3585 template <
typename E>
3586 template <
typename E2,
3587 typename std::enable_if<
RESULT_NS_IMPL::detail::failure_is_explicit_value_convertible<E,E2>::value,
int>::type>
3591 : m_failure(detail::forward<E2>(error))
3596 template <
typename E>
3597 template <
typename E2,
3598 typename std::enable_if<
RESULT_NS_IMPL::detail::failure_is_implicit_value_convertible<E,E2>::value,
int>::type>
3602 : m_failure(detail::forward<E2>(error))
3607 template <
typename E>
3608 template <
typename E2,
typename>
3612 : m_failure(other.error())
3617 template <
typename E>
3618 template <
typename E2,
typename>
3622 : m_failure(
static_cast<failure<E2>&&>(other).error())
3629 template <
typename E>
3630 template <
typename E2,
typename>
3638 m_failure = detail::forward<E2>(error);
3643 template <
typename E>
3644 template <
typename E2,
typename>
3650 m_failure = other.error();
3655 template <
typename E>
3656 template <
typename E2,
typename>
3662 m_failure =
static_cast<failure<E2>&&>(other).error();
3671 template <
typename E>
3674 &
noexcept ->
typename std::add_lvalue_reference<E>::
type
3679 template <
typename E>
3682 &&
noexcept ->
typename std::add_rvalue_reference<E>::
type
3684 using reference =
typename std::add_rvalue_reference<E>::type;
3686 return static_cast<reference>(m_failure);
3689 template <
typename E>
3693 ->
typename std::add_lvalue_reference<
typename std::add_const<E>::
type>::
type
3698 template <
typename E>
3702 ->
typename std::add_rvalue_reference<
typename std::add_const<E>::
type>::
type
3704 using reference =
typename std::add_rvalue_reference<
typename std::add_const<E>::type>::type;
3706 return static_cast<reference>(m_failure);
3717 template <
typename E1,
typename E2>
3719 auto RESULT_NS_IMPL::operator==(
const failure<E1>& lhs,
const failure<E2>& rhs)
3722 return lhs.error() == rhs.error();
3725 template <
typename E1,
typename E2>
3727 auto RESULT_NS_IMPL::operator!=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3730 return lhs.error() != rhs.error();
3733 template <
typename E1,
typename E2>
3735 auto RESULT_NS_IMPL::operator<(
const failure<E1>& lhs,
const failure<E2>& rhs)
3738 return lhs.error() < rhs.error();
3741 template <
typename E1,
typename E2>
3743 auto RESULT_NS_IMPL::operator>(
const failure<E1>& lhs,
const failure<E2>& rhs)
3746 return lhs.error() > rhs.error();
3749 template <
typename E1,
typename E2>
3751 auto RESULT_NS_IMPL::operator<=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3754 return lhs.error() <= rhs.error();
3757 template <
typename E1,
typename E2>
3759 auto RESULT_NS_IMPL::operator>=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3762 return lhs.error() >= rhs.error();
3769 template <
typename E>
3773 -> failure<
typename std::decay<E>::
type>
3775 using result_type = failure<
typename std::decay<E>::type>;
3778 detail::forward<E>(e)
3782 template <
typename E>
3785 noexcept -> failure<E&>
3787 using result_type = failure<E&>;
3789 return result_type{e.get()};
3792 template <
typename E,
typename...Args,
typename>
3798 return failure<E>(in_place, detail::forward<Args>(args)...);
3801 template <
typename E,
typename U,
typename...Args,
typename>
3807 return failure<E>(in_place, ilist, detail::forward<Args>(args)...);
3810 template <
typename E>
3813 #if __cplusplus
>= 201703L
3822 swap(lhs.error(), rhs.error());
3833 template <
typename T,
typename E,
bool IsTrivial>
3836 ::result_union(unit)
3843 template <
typename T,
typename E,
bool IsTrivial>
3844 template <
typename...Args>
3848 noexcept(std::is_nothrow_constructible<T, Args...>::value)
3849 : m_value(detail::forward<Args>(args)...),
3854 template <
typename T,
typename E,
bool IsTrivial>
3855 template <
typename...Args>
3859 noexcept(std::is_nothrow_constructible<E, Args...>::value)
3860 : m_error(detail::forward<Args>(args)...),
3869 template <
typename T,
typename E,
bool IsTrivial>
3871 auto RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::destroy()
3872 const noexcept ->
void
3885 template <
typename T,
typename E>
3888 ::result_union(unit)
3895 template <
typename T,
typename E>
3896 template <
typename...Args>
3900 noexcept(std::is_nothrow_constructible<T, Args...>::value)
3901 : m_value(detail::forward<Args>(args)...),
3906 template <
typename T,
typename E>
3907 template <
typename...Args>
3911 noexcept(std::is_nothrow_constructible<E, Args...>::value)
3912 : m_error(detail::forward<Args>(args)...),
3919 template <
typename T,
typename E>
3923 noexcept(std::is_nothrow_destructible<T>::value && std::is_nothrow_destructible<E>::value)
3932 template <
typename T,
typename E>
3934 auto RESULT_NS_IMPL::detail::result_union<T, E,
false>::destroy()
3938 m_value.~underlying_value_type();
3940 m_error.~underlying_error_type();
3952 template <
typename T,
typename E>
3954 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(unit)
3960 template <
typename T,
typename E>
3961 template <
typename...Args>
3963 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3966 )
noexcept(std::is_nothrow_constructible<T, Args...>::value)
3967 : storage{in_place, detail::forward<Args>(args)...}
3971 template <
typename T,
typename E>
3972 template <
typename...Args>
3974 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3977 )
noexcept(std::is_nothrow_constructible<E, Args...>::value)
3978 : storage(in_place_error, detail::forward<Args>(args)...)
3986 template <
typename T,
typename E>
3987 template <
typename...Args>
3989 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value(Args&&...args)
3990 noexcept(std::is_nothrow_constructible<T,Args...>::value)
3993 using value_type =
typename storage_type::underlying_value_type;
3995 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
3996 new (p) value_type(detail::forward<Args>(args)...);
3997 storage.m_has_value =
true;
4000 template <
typename T,
typename E>
4001 template <
typename...Args>
4003 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error(Args&&...args)
4004 noexcept(std::is_nothrow_constructible<E,Args...>::value)
4007 using error_type =
typename storage_type::underlying_error_type;
4009 auto* p =
static_cast<
void*>(std::addressof(storage.m_error));
4010 new (p) error_type(detail::forward<Args>(args)...);
4011 storage.m_has_value =
false;
4014 template <
typename T,
typename E>
4015 template <
typename Result>
4017 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error_from_result(
4021 if (other.storage.m_has_value) {
4024 construct_error(detail::forward<Result>(other).storage.m_error);
4029 template <
typename T,
typename E>
4030 template <
typename Result>
4032 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_from_result(
4036 if (other.storage.m_has_value) {
4037 construct_value_from_result_impl(
4038 std::is_lvalue_reference<T>{},
4039 detail::forward<Result>(other).storage.m_value
4042 construct_error(detail::forward<Result>(other).storage.m_error);
4046 template <
typename T,
typename E>
4047 template <
typename Value>
4049 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value(Value&& value)
4050 noexcept(std::is_nothrow_assignable<T,Value>::value)
4053 if (!storage.m_has_value) {
4055 construct_value(detail::forward<Value>(value));
4057 storage.m_value = detail::forward<Value>(value);
4061 template <
typename T,
typename E>
4062 template <
typename Error>
4064 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_error(Error&& error)
4065 noexcept(std::is_nothrow_assignable<E,Error>::value)
4068 if (storage.m_has_value) {
4070 construct_error(detail::forward<Error>(error));
4072 storage.m_error = detail::forward<Error>(error);
4076 template <
typename T,
typename E>
4077 template <
typename Result>
4079 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_from_result(Result&& other)
4082 if (other.storage.m_has_value != storage.m_has_value) {
4084 construct_from_result(detail::forward<Result>(other));
4085 }
else if (storage.m_has_value) {
4086 assign_value_from_result_impl(
4087 std::is_lvalue_reference<T>{},
4088 detail::forward<Result>(other)
4091 storage.m_error = detail::forward<Result>(other).storage.m_error;
4095 template <
typename T,
typename E>
4096 template <
typename ReferenceWrapper>
4098 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4100 ReferenceWrapper&& reference
4103 using value_type =
typename storage_type::underlying_value_type;
4105 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
4106 new (p) value_type(reference.get());
4107 storage.m_has_value =
true;
4110 template <
typename T,
typename E>
4111 template <
typename Value>
4113 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4116 )
noexcept(std::is_nothrow_constructible<T,Value>::value) ->
void
4118 using value_type =
typename storage_type::underlying_value_type;
4120 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
4121 new (p) value_type(detail::forward<Value>(value));
4122 storage.m_has_value =
true;
4125 template <
typename T,
typename E>
4126 template <
typename Result>
4128 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4134 storage.m_value = other.storage.m_value.get();
4137 template <
typename T,
typename E>
4138 template <
typename Result>
4140 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4145 storage.m_value = detail::forward<Result>(other).storage.m_value;
4153 template <
typename T,
typename E>
4156 ::result_trivial_copy_ctor_base_impl(
const result_trivial_copy_ctor_base_impl& other)
4157 noexcept(std::is_nothrow_copy_constructible<T>::value &&
4158 std::is_nothrow_copy_constructible<E>::value)
4161 using ctor_base = result_construct_base<T,E>;
4163 ctor_base::construct_from_result(
static_cast<
const ctor_base&>(other));
4170 template <
typename T,
typename E>
4173 ::result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
4174 noexcept(std::is_nothrow_move_constructible<T>::value &&
4175 std::is_nothrow_move_constructible<E>::value)
4178 using ctor_base = result_construct_base<T,E>;
4180 ctor_base::construct_from_result(
static_cast<ctor_base&&>(other));
4187 template <
typename T,
typename E>
4189 auto RESULT_NS_IMPL::detail::result_trivial_copy_assign_base_impl<T, E>
4190 ::operator=(
const result_trivial_copy_assign_base_impl& other)
4191 noexcept(std::is_nothrow_copy_constructible<T>::value &&
4192 std::is_nothrow_copy_constructible<E>::value &&
4193 std::is_nothrow_copy_assignable<T>::value &&
4194 std::is_nothrow_copy_assignable<E>::value)
4195 -> result_trivial_copy_assign_base_impl&
4197 using ctor_base = result_construct_base<T,E>;
4199 ctor_base::assign_from_result(
static_cast<
const ctor_base&>(other));
4207 template <
typename T,
typename E>
4209 auto RESULT_NS_IMPL::detail::result_trivial_move_assign_base_impl<T, E>
4210 ::operator=(result_trivial_move_assign_base_impl&& other)
4211 noexcept(std::is_nothrow_move_constructible<T>::value &&
4212 std::is_nothrow_move_constructible<E>::value &&
4213 std::is_nothrow_move_assignable<T>::value &&
4214 std::is_nothrow_move_assignable<E>::value)
4215 -> result_trivial_move_assign_base_impl&
4217 using ctor_base = result_construct_base<T,E>;
4219 ctor_base::assign_from_result(
static_cast<ctor_base&&>(other));
4223 template <
typename T,
typename E>
4225 auto RESULT_NS_IMPL::detail::result_error_extractor::get(
const result<T,E>& exp)
4226 noexcept ->
const E&
4228 return exp.m_storage.storage.m_error;
4231 template <
typename T,
typename E>
4233 auto RESULT_NS_IMPL::detail::result_error_extractor::get(result<T,E>& exp)
4236 return exp.m_storage.storage.m_error;
4239 template <
typename T,
typename E>
4241 auto RESULT_NS_IMPL::detail::extract_error(
const result<T,E>& exp)
noexcept ->
const E&
4243 return result_error_extractor::get(exp);
4246 template <
typename E>
4248 auto RESULT_NS_IMPL::detail::throw_bad_result_access(E&& error) ->
void
4250 #if defined(RESULT_DISABLE_EXCEPTIONS)
4253 "error attempting to access value from result containing error\n"
4257 using exception_type = bad_result_access<
4258 typename std::remove_const<
4259 typename std::remove_reference<E>::type
4263 throw exception_type{
4264 detail::forward<E>(error)
4269 template <
typename String,
typename E>
4276 #if defined(RESULT_DISABLE_EXCEPTIONS)
4277 const auto message_string = std::string{
4278 detail::forward<String>(message)
4280 std::fprintf(stderr,
"%s\n", message_string.c_str());
4283 using exception_type = bad_result_access<
4284 typename std::remove_const<
4285 typename std::remove_reference<E>::type
4289 throw exception_type{
4290 detail::forward<String>(message),
4291 detail::forward<E>(error)
4300 template <
typename T,
typename E>
4301 template <
typename U,
typename>
4305 : m_storage(in_place)
4310 template <
typename T,
typename E>
4311 template <
typename T2,
typename E2,
4312 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,
int>::type>
4317 : m_storage(detail::unit{})
4319 m_storage.construct_from_result(
4320 static_cast<
const result<T2,E2>&>(other).m_storage
4324 template <
typename T,
typename E>
4325 template <
typename T2,
typename E2,
4326 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_explicit_copy_convertible<T,E,T2,E2>::value,
int>::type>
4331 : m_storage(detail::unit{})
4333 m_storage.construct_from_result(
4334 static_cast<
const result<T2,E2>&>(other).m_storage
4338 template <
typename T,
typename E>
4339 template <
typename T2,
typename E2,
4340 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_implicit_move_convertible<T,E,T2,E2>::value,
int>::type>
4345 : m_storage(detail::unit{})
4347 m_storage.construct_from_result(
4348 static_cast<result<T2,E2>&&>(other).m_storage
4352 template <
typename T,
typename E>
4353 template <
typename T2,
typename E2,
4354 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_explicit_move_convertible<T,E,T2,E2>::value,
int>::type>
4359 : m_storage(detail::unit{})
4361 m_storage.construct_from_result(
4362 static_cast<result<T2,E2>&&>(other).m_storage
4368 template <
typename T,
typename E>
4369 template <
typename...Args,
typename>
4373 : m_storage(in_place, detail::forward<Args>(args)...)
4378 template <
typename T,
typename E>
4379 template <
typename U,
typename...Args,
typename>
4383 std::initializer_list<U> ilist,
4386 : m_storage(in_place, ilist, detail::forward<Args>(args)...)
4393 template <
typename T,
typename E>
4394 template <
typename...Args,
typename>
4398 : m_storage(in_place_error, detail::forward<Args>(args)...)
4403 template <
typename T,
typename E>
4404 template <
typename U,
typename...Args,
typename>
4408 std::initializer_list<U> ilist,
4411 : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
4418 template <
typename T,
typename E>
4419 template <
typename E2,
typename>
4423 : m_storage(in_place_error, e.error())
4428 template <
typename T,
typename E>
4429 template <
typename E2,
typename>
4433 : m_storage(in_place_error,
static_cast<E2&&>(e.error()))
4438 template <
typename T,
typename E>
4439 template <
typename U,
4440 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_explicit_value_convertible<T,U>::value,
int>::type>
4444 : m_storage(in_place, detail::forward<U>(value))
4449 template <
typename T,
typename E>
4450 template <
typename U,
4451 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_implicit_value_convertible<T,U>::value,
int>::type>
4455 : m_storage(in_place, detail::forward<U>(value))
4462 template <
typename T,
typename E>
4463 template <
typename T2,
typename E2,
typename>
4470 m_storage.assign_from_result(
4471 static_cast<
const result<T2,E2>&>(other).m_storage
4476 template <
typename T,
typename E>
4477 template <
typename T2,
typename E2,
typename>
4484 m_storage.assign_from_result(
4485 static_cast<result<T2,E2>&&>(other).m_storage
4490 template <
typename T,
typename E>
4491 template <
typename U,
typename>
4497 m_storage.assign_value(detail::forward<U>(value));
4501 template <
typename T,
typename E>
4502 template <
typename E2,
typename>
4508 m_storage.assign_error(other.error());
4512 template <
typename T,
typename E>
4513 template <
typename E2,
typename>
4519 m_storage.assign_error(
static_cast<E2&&>(other.error()));
4527 template <
typename T,
typename E>
4530 noexcept ->
typename std::remove_reference<T>::
type*
4536 #if __cplusplus
>= 201703L
4537 return std::addressof(**
this);
4543 template <
typename T,
typename E>
4546 const noexcept ->
typename std::remove_reference<
typename std::add_const<T>::
type>::
type*
4548 #if __cplusplus
>= 201703L
4549 return std::addressof(**
this);
4555 template <
typename T,
typename E>
4558 &
noexcept ->
typename std::add_lvalue_reference<T>::
type
4560 return m_storage.storage.m_value;
4563 template <
typename T,
typename E>
4566 &&
noexcept ->
typename std::add_rvalue_reference<T>::type
4568 using reference =
typename std::add_rvalue_reference<T>::type;
4570 return static_cast<reference>(m_storage.storage.m_value);
4573 template <
typename T,
typename E>
4576 const&
noexcept ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type
4578 return m_storage.storage.m_value;
4581 template <
typename T,
typename E>
4584 const&&
noexcept ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type
4586 using reference =
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
4588 return static_cast<reference>(m_storage.storage.m_value);
4593 template <
typename T,
typename E>
4598 return m_storage.storage.m_has_value;
4601 template <
typename T,
typename E>
4604 const noexcept ->
bool
4606 return m_storage.storage.m_has_value;
4609 template <
typename T,
typename E>
4612 const noexcept ->
bool
4614 return !m_storage.storage.m_has_value;
4622 #if defined(__clang__
)
4623 # pragma clang diagnostic push
4624 # pragma clang diagnostic ignored "-Wunused-value"
4625 #elif defined(__GNUC__)
4626 # pragma GCC diagnostic push
4627 # pragma GCC diagnostic ignored "-Wunused-value"
4628 #elif defined(_MSC_VER)
4631 # pragma warning(push)
4632 # pragma warning(disable:4172
)
4635 template <
typename T,
typename E>
4638 & ->
typename std::add_lvalue_reference<T>::
type
4640 return (has_value() ||
4641 (detail::throw_bad_result_access(m_storage.storage.m_error),
false),
4642 m_storage.storage.m_value
4646 template <
typename T,
typename E>
4649 && ->
typename std::add_rvalue_reference<T>::type
4651 using reference =
typename std::add_rvalue_reference<T>::type;
4653 return (has_value() ||
4654 (detail::throw_bad_result_access(
static_cast<E&&>(m_storage.storage.m_error)),
true),
4655 static_cast<reference>(m_storage.storage.m_value)
4659 template <
typename T,
typename E>
4662 const & ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type
4664 return (has_value() ||
4665 (detail::throw_bad_result_access(m_storage.storage.m_error),
true),
4666 m_storage.storage.m_value
4670 template <
typename T,
typename E>
4673 const && ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type
4675 using reference =
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
4677 return (has_value() ||
4678 (detail::throw_bad_result_access(
static_cast<
const E&&>(m_storage.storage.m_error)),
true),
4679 (
static_cast<reference>(m_storage.storage.m_value))
4683 #if defined(__clang__
)
4684 # pragma clang diagnostic pop
4685 #elif defined(__GNUC__)
4686 # pragma GCC diagnostic pop
4687 #elif defined(_MSC_VER)
4688 # pragma warning(pop)
4691 template <
typename T,
typename E>
4698 std::is_default_constructible<E>::value,
4699 "E must be default-constructible if 'error()' checks are used. "
4700 "This is to allow for default-constructed error states to represent the "
4704 return m_storage.storage.m_has_value
4706 : m_storage.storage.m_error;
4709 template <
typename T,
typename E>
4712 noexcept(std::is_nothrow_constructible<E>::value &&
4713 std::is_nothrow_move_constructible<E>::value) -> E
4716 std::is_default_constructible<E>::value,
4717 "E must be default-constructible if 'error()' checks are used. "
4718 "This is to allow for default-constructed error states to represent the "
4722 return m_storage.storage.m_has_value
4724 :
static_cast<E&&>(m_storage.storage.m_error);
4729 template <
typename T,
typename E>
4730 template <
typename String,
typename>
4733 & ->
typename std::add_lvalue_reference<T>::type
4735 return (has_value() ||
4736 (detail::throw_bad_result_access_message(
4737 detail::forward<String>(message),
4738 m_storage.storage.m_error
4740 m_storage.storage.m_value
4744 template <
typename T,
typename E>
4745 template <
typename String,
typename>
4748 && ->
typename std::add_rvalue_reference<T>::type
4750 using reference =
typename std::add_rvalue_reference<T>::type;
4752 return (has_value() ||
4753 (detail::throw_bad_result_access_message(
4754 detail::forward<String>(message),
4755 static_cast<E&&>(m_storage.storage.m_error)
4757 static_cast<reference>(m_storage.storage.m_value)
4761 template <
typename T,
typename E>
4762 template <
typename String,
typename>
4765 const & ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type
4767 return (has_value() ||
4768 (detail::throw_bad_result_access_message(
4769 detail::forward<String>(message),
4770 m_storage.storage.m_error
4772 m_storage.storage.m_value
4776 template <
typename T,
typename E>
4777 template <
typename String,
typename>
4780 const && ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type
4782 using reference =
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
4784 return (has_value() ||
4785 (detail::throw_bad_result_access_message(
4786 detail::forward<String>(message),
4787 static_cast<
const E&&>(m_storage.storage.m_error)
4789 (
static_cast<reference>(m_storage.storage.m_value))
4797 template <
typename T,
typename E>
4798 template <
typename U>
4801 const& ->
typename std::remove_reference<T>::
type
4803 return m_storage.storage.m_has_value
4804 ? m_storage.storage.m_value
4805 : detail::forward<U>(default_value);
4808 template <
typename T,
typename E>
4809 template <
typename U>
4812 && ->
typename std::remove_reference<T>::type
4814 return m_storage.storage.m_has_value
4815 ?
static_cast<T&&>(**
this)
4816 : detail::forward<U>(default_value);
4819 template <
typename T,
typename E>
4820 template <
typename U>
4823 const& -> error_type
4825 return m_storage.storage.m_has_value
4826 ? detail::forward<U>(default_error)
4827 : m_storage.storage.m_error;
4830 template <
typename T,
typename E>
4831 template <
typename U>
4836 return m_storage.storage.m_has_value
4837 ? detail::forward<U>(default_error)
4838 :
static_cast<E&&>(m_storage.storage.m_error);
4841 template <
typename T,
typename E>
4842 template <
typename U>
4845 const -> result<
typename std::decay<U>::type,E>
4847 return map([&value](
const T&){
4848 return detail::forward<U>(value);
4854 template <
typename T,
typename E>
4855 template <
typename Fn>
4858 const & -> detail::invoke_result_t<Fn,
const T&>
4860 using result_type = detail::invoke_result_t<Fn,
const T&>;
4864 "flat_map must return a result type or the program is ill-formed"
4868 ? detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value)
4869 : result_type(in_place_error, m_storage.storage.m_error);
4872 template <
typename T,
typename E>
4873 template <
typename Fn>
4876 && -> detail::invoke_result_t<Fn, T&&>
4878 using result_type = detail::invoke_result_t<Fn, T&&>;
4882 "flat_map must return a result type or the program is ill-formed"
4886 ? detail::invoke(detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value))
4887 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
4890 template <
typename T,
typename E>
4891 template <
typename Fn>
4894 const & -> result<detail::invoke_result_t<Fn,
const T&>,E>
4896 using result_type = detail::invoke_result_t<Fn,
const T&>;
4898 return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4901 template <
typename T,
typename E>
4902 template <
typename Fn>
4905 && -> result<detail::invoke_result_t<Fn,T&&>,E>
4907 using result_type = detail::invoke_result_t<Fn,T&&>;
4909 return static_cast<result<T,E>&&>(*
this).map_impl(
4910 std::is_void<result_type>{},
4911 detail::forward<Fn>(fn)
4917 template <
typename T,
typename E>
4918 template <
typename Fn>
4921 const & -> result<T, detail::invoke_result_t<Fn,
const E&>>
4923 using result_type = result<T, detail::invoke_result_t<Fn,
const E&>>;
4926 ? result_type(in_place_error, detail::invoke(
4927 detail::forward<Fn>(fn), m_storage.storage.m_error
4929 : result_type(in_place, m_storage.storage.m_value);
4932 template <
typename T,
typename E>
4933 template <
typename Fn>
4936 && -> result<T, detail::invoke_result_t<Fn,E&&>>
4938 using result_type = result<T, detail::invoke_result_t<Fn, E&&>>;
4941 ? result_type(in_place_error, detail::invoke(
4942 detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error)
4944 : result_type(
static_cast<T&&>(m_storage.storage.m_value));
4947 template <
typename T,
typename E>
4948 template <
typename Fn>
4951 const & -> detail::invoke_result_t<Fn,
const E&>
4953 using result_type = detail::invoke_result_t<Fn,
const E&>;
4957 "flat_map_error must return a result type or the program is ill-formed"
4961 ? result_type(in_place, m_storage.storage.m_value)
4962 : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4965 template <
typename T,
typename E>
4966 template <
typename Fn>
4969 && -> detail::invoke_result_t<Fn, E&&>
4971 using result_type = detail::invoke_result_t<Fn, E&&>;
4975 "flat_map_error must return a result type or the program is ill-formed"
4979 ? result_type(in_place,
static_cast<T&&>(m_storage.storage.m_value))
4980 : detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error));
4987 template <
typename T,
typename E>
4988 template <
typename Fn>
4990 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4991 const & -> result<
void,E>
4993 using result_type = result<
void, E>;
4996 ? (detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value), result_type{})
4997 : result_type(in_place_error, m_storage.storage.m_error);
5000 template <
typename T,
typename E>
5001 template <
typename Fn>
5003 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
5004 const & -> result<detail::invoke_result_t<Fn,
const T&>,E>
5006 using invoke_result_type = detail::invoke_result_t<Fn,
const T&>;
5007 using result_type = result<invoke_result_type, E>;
5010 ? result_type(in_place, detail::invoke(
5011 detail::forward<Fn>(fn), m_storage.storage.m_value
5013 : result_type(in_place_error, m_storage.storage.m_error);
5016 template <
typename T,
typename E>
5017 template <
typename Fn>
5019 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
5020 && -> result<
void,E>
5022 using result_type = result<
void, E>;
5026 detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value)
5028 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5031 template <
typename T,
typename E>
5032 template <
typename Fn>
5034 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
5035 && -> result<detail::invoke_result_t<Fn,T&&>,E>
5037 using invoke_result_type = detail::invoke_result_t<Fn,T&&>;
5038 using result_type = result<invoke_result_type, E>;
5041 ? result_type(in_place, detail::invoke(
5042 detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value)
5044 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5055 template <
typename E>
5059 : m_storage(in_place)
5064 template <
typename E>
5065 template <
typename U,
typename E2,
typename>
5069 : m_storage(detail::unit{})
5071 m_storage.construct_error_from_result(
5072 static_cast<
const result<U,E2>&>(other).m_storage
5076 template <
typename E>
5077 template <
typename U,
typename E2,
typename>
5081 : m_storage(detail::unit{})
5083 m_storage.construct_error_from_result(
5084 static_cast<result<U,E2>&&>(other).m_storage
5091 template <
typename E>
5095 : m_storage(in_place)
5100 template <
typename E>
5101 template <
typename...Args,
typename>
5105 : m_storage(in_place_error, detail::forward<Args>(args)...)
5110 template <
typename E>
5111 template <
typename U,
typename...Args,
typename>
5114 std::initializer_list<U> ilist,
5117 : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
5124 template <
typename E>
5125 template <
typename E2,
typename>
5129 : m_storage(in_place_error, e.error())
5134 template <
typename E>
5135 template <
typename E2,
typename>
5139 : m_storage(in_place_error,
static_cast<E2&&>(e.error()))
5146 template <
typename E>
5147 template <
typename E2,
typename>
5153 m_storage.assign_from_result(other.m_storage);
5157 template <
typename E>
5158 template <
typename E2,
typename>
5164 m_storage.assign_from_result(
static_cast<result<
void,E2>&&>(other).m_storage);
5168 template <
typename E>
5169 template <
typename E2,
typename>
5175 m_storage.assign_error(other.error());
5179 template <
typename E>
5180 template <
typename E2,
typename>
5186 m_storage.assign_error(
static_cast<E2&&>(other.error()));
5194 template <
typename E>
5202 template <
typename E>
5205 const noexcept ->
bool
5207 return m_storage.storage.m_has_value;
5210 template <
typename E>
5213 const noexcept ->
bool
5220 template <
typename E>
5227 (detail::throw_bad_result_access(m_storage.storage.m_error),
true)
5231 template <
typename E>
5238 (detail::throw_bad_result_access(
static_cast<E&&>(m_storage.storage.m_error)),
true)
5242 template <
typename E>
5249 return has_value() ? E{} : m_storage.storage.m_error;
5252 template <
typename E>
5258 return has_value() ? E{} :
static_cast<E&&>(m_storage.storage.m_error);
5263 template <
typename E>
5264 template <
typename String,
typename>
5270 detail::throw_bad_result_access_message(
5271 detail::forward<String>(message),
5272 m_storage.storage.m_error
5277 template <
typename E>
5278 template <
typename String,
typename>
5284 detail::throw_bad_result_access_message(
5285 detail::forward<String>(message),
5286 static_cast<E&&>(m_storage.storage.m_error)
5295 template <
typename E>
5296 template <
typename U>
5299 const & -> error_type
5302 ? detail::forward<U>(default_error)
5303 : m_storage.storage.m_error;
5306 template <
typename E>
5307 template <
typename U>
5313 ? detail::forward<U>(default_error)
5314 :
static_cast<E&&>(m_storage.storage.m_error);
5317 template <
typename E>
5318 template <
typename U>
5321 const -> result<
typename std::decay<U>::
type,E>
5323 return map([&value]{
5324 return detail::forward<U>(value);
5330 template <
typename E>
5331 template <
typename Fn>
5334 const & -> detail::invoke_result_t<Fn>
5336 using result_type = detail::invoke_result_t<Fn>;
5340 "flat_map must return a result type or the program is ill-formed"
5344 ? detail::invoke(detail::forward<Fn>(fn))
5345 : result_type(in_place_error, m_storage.storage.m_error);
5348 template <
typename E>
5349 template <
typename Fn>
5352 && -> detail::invoke_result_t<Fn>
5354 using result_type = detail::invoke_result_t<Fn>;
5358 "flat_map must return a result type or the program is ill-formed"
5362 ? detail::invoke(detail::forward<Fn>(fn))
5363 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5366 template <
typename E>
5367 template <
typename Fn>
5370 const & -> result<detail::invoke_result_t<Fn>,E>
5372 using result_type = detail::invoke_result_t<Fn>;
5374 return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
5377 template <
typename E>
5378 template <
typename Fn>
5381 && -> result<detail::invoke_result_t<Fn>,E>
5383 using result_type = detail::invoke_result_t<Fn>;
5385 return static_cast<result<
void,E>&&>(*
this).map_impl(
5386 std::is_void<result_type>{},
5387 detail::forward<Fn>(fn)
5393 template <
typename E>
5394 template <
typename Fn>
5397 const & -> result<
void, detail::invoke_result_t<Fn,
const E&>>
5399 using result_type = result<
void, detail::invoke_result_t<Fn,
const E&>>;
5403 : result_type(in_place_error, detail::invoke(
5404 detail::forward<Fn>(fn), m_storage.storage.m_error
5408 template <
typename E>
5409 template <
typename Fn>
5412 && -> result<
void, detail::invoke_result_t<Fn,E&&>>
5414 using result_type = result<
void, detail::invoke_result_t<Fn, E&&>>;
5418 : result_type(in_place_error,
5419 detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error)
5423 template <
typename E>
5424 template <
typename Fn>
5427 const & -> detail::invoke_result_t<Fn,
const E&>
5429 using result_type = detail::invoke_result_t<Fn,
const E&>;
5433 "flat_map_error must return a result type or the program is ill-formed"
5436 std::is_default_constructible<
typename result_type::value_type>::value,
5437 "flat_map_error for result<void,E> requires the new T type to be default-"
5443 : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
5446 template <
typename E>
5447 template <
typename Fn>
5450 && -> detail::invoke_result_t<Fn,E&&>
5452 using result_type = detail::invoke_result_t<Fn,E&&>;
5456 "flat_map_error must return a result type or the program is ill-formed"
5459 std::is_default_constructible<
typename result_type::value_type>::value,
5460 "flat_map_error for result<void,E> requires the new T type to be default-"
5466 : detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error));
5473 template <
typename E>
5474 template <
typename Fn>
5476 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::true_type, Fn&& fn)
5477 const & -> result<
void,E>
5479 using result_type = result<
void, E>;
5482 ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5483 : result_type(in_place_error, m_storage.storage.m_error);
5486 template <
typename E>
5487 template <
typename Fn>
5489 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::false_type, Fn&& fn)
5490 const & -> result<detail::invoke_result_t<Fn>,E>
5492 using invoke_result_type = detail::invoke_result_t<Fn>;
5493 using result_type = result<invoke_result_type, E>;
5496 ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5497 : result_type(in_place_error, m_storage.storage.m_error);
5500 template <
typename E>
5501 template <
typename Fn>
5503 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::true_type, Fn&& fn)
5504 && -> result<
void,E>
5506 using result_type = result<
void, E>;
5509 ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5510 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5513 template <
typename E>
5514 template <
typename Fn>
5516 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::false_type, Fn&& fn)
5517 && -> result<detail::invoke_result_t<Fn>,E>
5519 using invoke_result_type = detail::invoke_result_t<Fn>;
5520 using result_type = result<invoke_result_type, E>;
5523 ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5524 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5535 template <
typename T1,
typename E1,
typename T2,
typename E2>
5538 const result<T2,E2>& rhs)
5541 return (lhs.has_value() == rhs.has_value())
5545 : detail::extract_error(lhs) == detail::extract_error(rhs)
5550 template <
typename T1,
typename E1,
typename T2,
typename E2>
5553 const result<T2,E2>& rhs)
5556 return (lhs.has_value() == rhs.has_value())
5560 : detail::extract_error(lhs) != detail::extract_error(rhs)
5565 template <
typename T1,
typename E1,
typename T2,
typename E2>
5568 const result<T2,E2>& rhs)
5571 return (lhs.has_value() == rhs.has_value())
5575 : detail::extract_error(lhs) >= detail::extract_error(rhs)
5577 :
static_cast<
int>(
static_cast<
bool>(lhs)) >=
static_cast<
int>(
static_cast<
bool>(rhs));
5580 template <
typename T1,
typename E1,
typename T2,
typename E2>
5583 const result<T2,E2>& rhs)
5586 return (lhs.has_value() == rhs.has_value())
5590 : detail::extract_error(lhs) <= detail::extract_error(rhs)
5592 :
static_cast<
int>(
static_cast<
bool>(lhs)) <=
static_cast<
int>(
static_cast<
bool>(rhs));
5595 template <
typename T1,
typename E1,
typename T2,
typename E2>
5598 const result<T2,E2>& rhs)
5601 return (lhs.has_value() == rhs.has_value())
5605 : detail::extract_error(lhs) > detail::extract_error(rhs)
5607 :
static_cast<
int>(
static_cast<
bool>(lhs)) >
static_cast<
int>(
static_cast<
bool>(rhs));
5610 template <
typename T1,
typename E1,
typename T2,
typename E2>
5613 const result<T2,E2>& rhs)
5616 return (lhs.has_value() == rhs.has_value())
5620 : detail::extract_error(lhs) < detail::extract_error(rhs)
5622 :
static_cast<
int>(
static_cast<
bool>(lhs)) <
static_cast<
int>(
static_cast<
bool>(rhs));
5628 template <
typename E1,
typename E2>
5631 const result<
void,E2>& rhs)
5634 return lhs.has_value() == rhs.has_value()
5638 : detail::extract_error(lhs) == detail::extract_error(rhs)
5643 template <
typename E1,
typename E2>
5646 const result<
void,E2>& rhs)
5649 return lhs.has_value() == rhs.has_value()
5653 : detail::extract_error(lhs) != detail::extract_error(rhs)
5658 template <
typename E1,
typename E2>
5661 const result<
void,E2>& rhs)
5664 return lhs.has_value() == rhs.has_value()
5668 : detail::extract_error(lhs) >= detail::extract_error(rhs)
5670 :
static_cast<
int>(
static_cast<
bool>(lhs)) >=
static_cast<
int>(
static_cast<
bool>(rhs));
5673 template <
typename E1,
typename E2>
5676 const result<
void,E2>& rhs)
5679 return lhs.has_value() == rhs.has_value()
5683 : detail::extract_error(lhs) <= detail::extract_error(rhs)
5685 :
static_cast<
int>(
static_cast<
bool>(lhs)) <=
static_cast<
int>(
static_cast<
bool>(rhs));
5688 template <
typename E1,
typename E2>
5691 const result<
void,E2>& rhs)
5694 return lhs.has_value() == rhs.has_value()
5698 : detail::extract_error(lhs) > detail::extract_error(rhs)
5700 :
static_cast<
int>(
static_cast<
bool>(lhs)) >
static_cast<
int>(
static_cast<
bool>(rhs));
5703 template <
typename E1,
typename E2>
5706 const result<
void,E2>& rhs)
5709 return lhs.has_value() == rhs.has_value()
5713 : detail::extract_error(lhs) < detail::extract_error(rhs)
5715 :
static_cast<
int>(
static_cast<
bool>(lhs)) <
static_cast<
int>(
static_cast<
bool>(rhs));
5721 template <
typename T,
typename E,
typename U,
typename>
5723 auto RESULT_NS_IMPL::operator==(
const result<T,E>& exp,
const U& value)
5726 return (exp.has_value() && *exp == value);
5729 template <
typename T,
typename U,
typename E,
typename>
5731 auto RESULT_NS_IMPL::operator==(
const T& value,
const result<U,E>& exp)
5734 return (exp.has_value() && *exp == value);
5737 template <
typename T,
typename E,
typename U,
typename>
5739 auto RESULT_NS_IMPL::operator!=(
const result<T,E>& exp,
const U& value)
5742 return exp.has_value() ? *exp != value :
true;
5745 template <
typename T,
typename U,
typename E,
typename>
5747 auto RESULT_NS_IMPL::operator!=(
const T& value,
const result<U,E>& exp)
5750 return exp.has_value() ? value != *exp :
true;
5753 template <
typename T,
typename E,
typename U,
typename>
5755 auto RESULT_NS_IMPL::operator<=(
const result<T,E>& exp,
const U& value)
5758 return exp.has_value() ? *exp <= value :
false;
5761 template <
typename T,
typename U,
typename E,
typename>
5763 auto RESULT_NS_IMPL::operator<=(
const T& value,
const result<U,E>& exp)
5766 return exp.has_value() ? value <= *exp :
true;
5769 template <
typename T,
typename E,
typename U,
typename>
5771 auto RESULT_NS_IMPL::operator>=(
const result<T,E>& exp,
const U& value)
5774 return exp.has_value() ? *exp >= value :
true;
5777 template <
typename T,
typename U,
typename E,
typename>
5779 auto RESULT_NS_IMPL::operator>=(
const T& value,
const result<U,E>& exp)
5782 return exp.has_value() ? value >= *exp :
false;
5785 template <
typename T,
typename E,
typename U,
typename>
5787 auto RESULT_NS_IMPL::operator<(
const result<T,E>& exp,
const U& value)
5790 return exp.has_value() ? *exp < value :
false;
5793 template <
typename T,
typename U,
typename E,
typename>
5795 auto RESULT_NS_IMPL::operator<(
const T& value,
const result<U,E>& exp)
5798 return exp.has_value() ? value < *exp :
true;
5801 template <
typename T,
typename E,
typename U,
typename>
5803 auto RESULT_NS_IMPL::operator>(
const result<T,E>& exp,
const U& value)
5806 return exp.has_value() ? *exp > value :
false;
5809 template <
typename T,
typename U,
typename E,
typename>
5811 auto RESULT_NS_IMPL::operator>(
const T& value,
const result<U,E>& exp)
5814 return exp.has_value() ? value > *exp :
true;
5819 template <
typename T,
typename E,
typename U>
5821 auto RESULT_NS_IMPL::operator==(
const result<T,E>& exp,
const failure<U>& error)
5824 return exp.has_error() ? detail::extract_error(exp) == error.error() :
false;
5827 template <
typename T,
typename U,
typename E>
5829 auto RESULT_NS_IMPL::operator==(
const failure<T>& error,
const result<E,U>& exp)
5832 return exp.has_error() ? error.error() == detail::extract_error(exp) :
false;
5835 template <
typename T,
typename E,
typename U>
5837 auto RESULT_NS_IMPL::operator!=(
const result<T,E>& exp,
const failure<U>& error)
5840 return exp.has_error() ? detail::extract_error(exp) != error.error() :
true;
5843 template <
typename T,
typename U,
typename E>
5845 auto RESULT_NS_IMPL::operator!=(
const failure<T>& error,
const result<E,U>& exp)
5848 return exp.has_error() ? error.error() != detail::extract_error(exp) :
true;
5851 template <
typename T,
typename E,
typename U>
5853 auto RESULT_NS_IMPL::operator<=(
const result<T,E>& exp,
const failure<U>& error)
5856 return exp.has_error() ? detail::extract_error(exp) <= error.error() :
true;
5859 template <
typename T,
typename U,
typename E>
5861 auto RESULT_NS_IMPL::operator<=(
const failure<T>& error,
const result<E,U>& exp)
5864 return exp.has_error() ? error.error() <= detail::extract_error(exp) :
false;
5867 template <
typename T,
typename E,
typename U>
5869 auto RESULT_NS_IMPL::operator>=(
const result<T,E>& exp,
const failure<U>& error)
5872 return exp.has_error() ? detail::extract_error(exp) >= error.error() :
false;
5875 template <
typename T,
typename U,
typename E>
5877 auto RESULT_NS_IMPL::operator>=(
const failure<T>& error,
const result<E,U>& exp)
5880 return exp.has_error() ? error.error() >= detail::extract_error(exp) :
true;
5883 template <
typename T,
typename E,
typename U>
5885 auto RESULT_NS_IMPL::operator<(
const result<T,E>& exp,
const failure<U>& error)
5888 return exp.has_error() ? detail::extract_error(exp) < error.error() :
true;
5891 template <
typename T,
typename U,
typename E>
5893 auto RESULT_NS_IMPL::operator<(
const failure<T>& error,
const result<E,U>& exp)
5896 return exp.has_error() ? error.error() < detail::extract_error(exp) :
false;
5899 template <
typename T,
typename E,
typename U>
5901 auto RESULT_NS_IMPL::operator>(
const result<T,E>& exp,
const failure<U>& error)
5904 return exp.has_error() ? detail::extract_error(exp) > error.error() :
false;
5907 template <
typename T,
typename U,
typename E>
5909 auto RESULT_NS_IMPL::operator>(
const failure<T>& error,
const result<E,U>& exp)
5912 return exp.has_error() ? error.error() > detail::extract_error(exp) :
true;
5919 template <
typename T,
typename E>
5922 #if __cplusplus
>= 201703L
5935 if (lhs.has_value() == rhs.has_value()) {
5936 if (lhs.has_value()) {
5939 auto& lhs_error = detail::result_error_extractor::get(lhs);
5940 auto& rhs_error = detail::result_error_extractor::get(rhs);
5942 swap(lhs_error, rhs_error);
5946 auto temp =
static_cast<result<T,E>&&>(lhs);
5947 lhs =
static_cast<result<T,E>&&>(rhs);
5948 rhs =
static_cast<result<T,E>&&>(temp);
5952 template <
typename E>
5955 #if __cplusplus
>= 201703L
5967 if (lhs.has_value() == rhs.has_value()) {
5968 if (lhs.has_error()) {
5969 auto& lhs_error = detail::result_error_extractor::get(lhs);
5970 auto& rhs_error = detail::result_error_extractor::get(rhs);
5972 swap(lhs_error, rhs_error);
5976 auto temp =
static_cast<result<
void,E>&&>(lhs);
5977 lhs =
static_cast<result<
void,E>&&>(rhs);
5978 rhs =
static_cast<result<
void,E>&&>(temp);
5982 #if defined(__clang__
)
5983 # pragma clang diagnostic pop
5986 #undef RESULT_NAMESPACE_INTERNAL
5987 #undef RESULT_NS_IMPL
5988 #undef RESULT_CPP14_CONSTEXPR
5989 #undef RESULT_CPP17_INLINE
5990 #undef RESULT_INLINE_VISIBILITY
5991 #undef RESULT_NODISCARD
5992 #undef RESULT_WARN_UNUSED