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;
2380 template <
typename String,
2381 typename =
typename std::enable_if<(
2382 std::is_convertible<String,
const std::string&>::value &&
2383 std::is_copy_constructible<E>::value
2386 template <
typename String,
2387 typename =
typename std::enable_if<(
2388 std::is_convertible<String,
const std::string&>::value &&
2389 std::is_move_constructible<E>::value
2417 template <
typename U>
2419 constexpr auto value_or(U&& default_value)
2420 const & ->
typename std::remove_reference<T>::
type;
2421 template <
typename U>
2424 && ->
typename std::remove_reference<T>::type;
2445 template <
typename U>
2447 constexpr auto error_or(U&& default_error)
const & -> error_type;
2448 template <
typename U>
2473 template <
typename U>
2475 constexpr auto and_then(U&& value)
const -> result<
typename std::decay<U>::type,E>;
2504 template <
typename Fn>
2506 constexpr auto flat_map(Fn&& fn)
const & -> detail::invoke_result_t<Fn,
const T&>;
2507 template <
typename Fn>
2538 template <
typename Fn>
2540 constexpr auto map(Fn&& fn)
const & -> result<detail::invoke_result_t<Fn,
const T&>,E>;
2541 template <
typename Fn>
2575 template <
typename Fn>
2577 constexpr auto map_error(Fn&& fn)
2578 const & -> result<T, detail::invoke_result_t<Fn,
const E&>>;
2579 template <
typename Fn>
2582 && -> result<T, detail::invoke_result_t<Fn,E&&>>;
2612 template <
typename Fn>
2614 constexpr auto flat_map_error(Fn&& fn)
2615 const & -> detail::invoke_result_t<Fn,
const E&>;
2616 template <
typename Fn>
2619 && -> detail::invoke_result_t<Fn, E&&>;
2627 detail::result_storage<T,E> m_storage;
2638 template <
typename Fn>
2639 constexpr auto map_impl(std::true_type, Fn&& fn)
const & -> result<
void,E>;
2640 template <
typename Fn>
2641 constexpr auto map_impl(std::false_type, Fn&& fn)
const & -> result<detail::invoke_result_t<Fn,
const T&>,E>;
2642 template <
typename Fn>
2644 template <
typename Fn>
2645 RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn,T&&>,E>;
2658 template <
typename E>
2664 !std::is_void<
typename std::decay<E>::type>::value,
2665 "It is ill-formed for E to be (possibly CV-qualified) void type" 2668 !std::is_abstract<E>::value,
2669 "It is ill-formed for E to be abstract type" 2672 !
is_failure<
typename std::decay<E>::type>::value,
2673 "It is ill-formed for E to be a (possibly CV-qualified) 'failure' type" 2676 !std::is_reference<E>::value,
2677 "It is ill-formed for E to be a reference type. " 2678 "Only T types may be lvalue references" 2683 friend detail::result_error_extractor;
2685 template <
typename T2,
typename E2>
2686 friend class result;
2693 using value_type =
void;
2694 using error_type = E;
2695 using failure_type = failure<E>;
2697 template <
typename U>
2698 using rebind = result<U,E>;
2714 constexpr result()
noexcept;
2737 constexpr result(
const result& other) =
default;
2760 constexpr result(result&& other) =
default;
2785 template <
typename U,
typename E2,
2786 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2787 explicit result(
const result<U,E2>& other)
2812 template <
typename U,
typename E2,
2813 typename =
typename std::enable_if<std::is_constructible<E,E2>::value>::type>
2814 explicit result(result<U,E2>&& other)
2851 template <
typename...Args,
2852 typename =
typename std::enable_if<std::is_constructible<E,Args...>::value>::type>
2875 template <
typename U,
typename...Args,
2876 typename =
typename std::enable_if<std::is_constructible<E, std::initializer_list<U>&, Args...>::value>::type>
2878 std::initializer_list<U> ilist,
2903 template <
typename E2,
2904 typename =
typename std::enable_if<std::is_constructible<E,
const E2&>::value>::type>
2905 constexpr result(
const failure<E2>& e)
2907 template <
typename E2,
2908 typename =
typename std::enable_if<std::is_constructible<E,E2&&>::value>::type>
2909 constexpr result(failure<E2>&& e)
2929 auto operator=(
const result& other) -> result& =
default;
2945 auto operator=(result&& other) -> result& =
default;
2964 template <
typename E2,
2965 typename =
typename std::enable_if<std::is_nothrow_constructible<E,
const E2&>::value &&
2966 std::is_assignable<E&,
const E2&>::value>::type>
2967 auto operator=(
const result<
void,E2>& other)
2987 template <
typename E2,
2988 typename =
typename std::enable_if<std::is_nothrow_constructible<E,E2&&>::value &&
2989 std::is_assignable<E&,E2&&>::value>::type>
2990 auto operator=(result<
void,E2>&& other)
3006 template <
typename E2,
3007 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,
const E2&>::value>::type>
3008 auto operator=(
const failure<E2>& other)
3010 template <
typename E2,
3011 typename =
typename std::enable_if<detail::result_is_failure_assignable<E,E2&&>::value>::type>
3012 auto operator=(failure<E2>&& other)
3045 constexpr explicit operator bool()
const noexcept;
3049 constexpr auto has_value()
const noexcept ->
bool;
3053 constexpr auto has_error()
const noexcept ->
bool;
3094 constexpr auto error()
const &
3105 template <
typename String,
3106 typename =
typename std::enable_if<(
3107 std::is_convertible<String,
const std::string&>::value &&
3108 std::is_copy_constructible<E>::value
3111 template <
typename String,
3112 typename =
typename std::enable_if<(
3113 std::is_convertible<String,
const std::string&>::value &&
3114 std::is_move_constructible<E>::value
3126 template <
typename U>
3128 constexpr auto error_or(U&& default_error)
const & -> error_type;
3129 template <
typename U>
3137 template <
typename U>
3139 constexpr auto and_then(U&& value)
const -> result<
typename std::decay<U>::
type,E>;
3167 template <
typename Fn>
3169 constexpr auto flat_map(Fn&& fn)
const & -> detail::invoke_result_t<Fn>;
3170 template <
typename Fn>
3200 template <
typename Fn>
3202 constexpr auto map(Fn&& fn)
const & -> result<detail::invoke_result_t<Fn>,E>;
3203 template <
typename Fn>
3210 template <
typename Fn>
3211 constexpr auto map_error(Fn&& fn)
const & -> result<
void, detail::invoke_result_t<Fn,
const E&>>;
3212 template <
typename Fn>
3214 auto map_error(Fn&& fn) && -> result<
void, detail::invoke_result_t<Fn,E&&>>;
3220 template <
typename Fn>
3222 constexpr auto flat_map_error(Fn&& fn)
const & -> detail::invoke_result_t<Fn,
const E&>;
3223 template <
typename Fn>
3233 detail::result_storage<detail::unit,E> m_storage;
3244 template <
typename Fn>
3245 constexpr auto map_impl(std::true_type, Fn&& fn)
const & -> result<
void,E>;
3246 template <
typename Fn>
3247 constexpr auto map_impl(std::false_type, Fn&& fn)
const & -> result<detail::invoke_result_t<Fn>,E>;
3248 template <
typename Fn>
3250 template <
typename Fn>
3251 RESULT_CPP14_CONSTEXPR auto map_impl(std::false_type, Fn&& fn) && -> result<detail::invoke_result_t<Fn>,E>;
3263 template <
typename T1,
typename E1,
typename T2,
typename E2>
3264 constexpr auto operator==(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3266 template <
typename T1,
typename E1,
typename T2,
typename E2>
3267 constexpr auto operator!=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3269 template <
typename T1,
typename E1,
typename T2,
typename E2>
3270 constexpr auto operator>=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3272 template <
typename T1,
typename E1,
typename T2,
typename E2>
3273 constexpr auto operator<=(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3275 template <
typename T1,
typename E1,
typename T2,
typename E2>
3276 constexpr auto operator>(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3278 template <
typename T1,
typename E1,
typename T2,
typename E2>
3279 constexpr auto operator<(
const result<T1,E1>& lhs,
const result<T2,E2>& rhs)
3284 template <
typename E1,
typename E2>
3285 constexpr auto operator==(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3287 template <
typename E1,
typename E2>
3288 constexpr auto operator!=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3290 template <
typename E1,
typename E2>
3291 constexpr auto operator>=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3293 template <
typename E1,
typename E2>
3294 constexpr auto operator<=(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3296 template <
typename E1,
typename E2>
3297 constexpr auto operator>(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3299 template <
typename E1,
typename E2>
3300 constexpr auto operator<(
const result<
void,E1>& lhs,
const result<
void,E2>& rhs)
3305 template <
typename T,
typename E,
typename U,
3306 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3307 constexpr auto operator==(
const result<T,E>& exp,
const U& value)
3309 template <
typename T,
typename U,
typename E,
3310 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3311 constexpr auto operator==(
const T& value,
const result<U,E>& exp)
3313 template <
typename T,
typename E,
typename U,
3314 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3315 constexpr auto operator!=(
const result<T,E>& exp,
const U& value)
3317 template <
typename T,
typename U,
typename E,
3318 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3319 constexpr auto operator!=(
const T& value,
const result<U,E>& exp)
3321 template <
typename T,
typename E,
typename U,
3322 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3323 constexpr auto operator<=(
const result<T,E>& exp,
const U& value)
3325 template <
typename T,
typename U,
typename E,
3326 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3327 constexpr auto operator<=(
const T& value,
const result<U,E>& exp)
3329 template <
typename T,
typename E,
typename U,
3330 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3331 constexpr auto operator>=(
const result<T,E>& exp,
const U& value)
3333 template <
typename T,
typename U,
typename E,
3334 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3335 constexpr auto operator>=(
const T& value,
const result<U,E>& exp)
3337 template <
typename T,
typename E,
typename U,
3338 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3339 constexpr auto operator<(
const result<T,E>& exp,
const U& value)
3341 template <
typename T,
typename U,
typename E,
3342 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3343 constexpr auto operator<(
const T& value,
const result<U,E>& exp)
3345 template <
typename T,
typename E,
typename U,
3346 typename =
typename std::enable_if<!std::is_same<T,
void>::value>::type>
3347 constexpr auto operator>(
const result<T,E>& exp,
const U& value)
3349 template <
typename T,
typename U,
typename E,
3350 typename =
typename std::enable_if<!std::is_same<U,
void>::value>::type>
3351 constexpr auto operator>(
const T& value,
const result<U,E>& exp)
3356 template <
typename T,
typename E,
typename U>
3357 constexpr auto operator==(
const result<T,E>& exp,
const failure<U>& value)
3359 template <
typename T,
typename U,
typename E>
3360 constexpr auto operator==(
const failure<T>& value,
const result<E,U>& exp)
3362 template <
typename T,
typename E,
typename U>
3363 constexpr auto operator!=(
const result<T,E>& exp,
const failure<U>& value)
3365 template <
typename T,
typename U,
typename E>
3366 constexpr auto operator!=(
const failure<T>& value,
const result<E,U>& exp)
3368 template <
typename T,
typename E,
typename U>
3369 constexpr auto operator<=(
const result<T,E>& exp,
const failure<U>& value)
3371 template <
typename T,
typename U,
typename E>
3372 constexpr auto operator<=(
const failure<T>& value,
const result<E,U>& exp)
3374 template <
typename T,
typename E,
typename U>
3375 constexpr auto operator>=(
const result<T,E>& exp,
const failure<U>& value)
3377 template <
typename T,
typename U,
typename E>
3378 constexpr auto operator>=(
const failure<T>& value,
const result<E,U>& exp)
3380 template <
typename T,
typename E,
typename U>
3381 constexpr auto operator<(
const result<T,E>& exp,
const failure<U>& value)
3383 template <
typename T,
typename U,
typename E>
3384 constexpr auto operator<(
const failure<T>& value,
const result<E,U>& exp)
3386 template <
typename T,
typename E,
typename U>
3387 constexpr auto operator>(
const result<T,E>& exp,
const failure<U>& value)
3389 template <
typename T,
typename U,
typename E>
3390 constexpr auto operator>(
const failure<T>& value,
const result<E,U>& exp)
3402 template <
typename T,
typename E>
3403 auto swap(result<T,E>& lhs, result<T,E>& rhs)
3404 #if __cplusplus
>= 201703L
3414 template <
typename E>
3415 auto swap(result<
void,E>& lhs, result<
void,E>& rhs)
3416 #if __cplusplus
>= 201703L
3432 template <
typename T,
typename E>
3435 auto operator()(
const RESULT_NS_IMPL::result<T,E>& x)
const -> std::size_t
3437 if (x.has_value()) {
3438 return std::hash<T>{}(*x) + 1;
3440 return std::hash<E>{}(::
RESULT_NS_IMPL::detail::extract_error(x));
3444 template <
typename E>
3447 auto operator()(
const RESULT_NS_IMPL::result<
void,E>& x)
const -> std::size_t
3449 if (x.has_value()) {
3452 return std::hash<E>{}(::
RESULT_NS_IMPL::detail::extract_error(x));
3458 #if !defined(RESULT_DISABLE_EXCEPTIONS) 3468 template <
typename E>
3469 template <
typename E2,
typename>
3472 : logic_error{
"error attempting to access value from result containing error"},
3473 m_error(detail::forward<E2>(error))
3478 template <
typename E>
3479 template <
typename E2,
typename>
3482 const char* what_arg,
3484 ) : logic_error{what_arg},
3485 m_error(detail::forward<E2>(error))
3490 template <
typename E>
3491 template <
typename E2,
typename>
3494 const std::string& what_arg,
3496 ) : logic_error{what_arg},
3497 m_error(detail::forward<E2>(error))
3506 template <
typename E>
3514 template <
typename E>
3519 return static_cast<E&&>(m_error);
3522 template <
typename E>
3525 const &
noexcept ->
const E&
3530 template <
typename E>
3533 const &&
noexcept ->
const E&&
3535 return static_cast<
const E&&>(m_error);
3548 template <
typename E>
3549 template <
typename...Args,
typename>
3553 : m_failure(detail::forward<Args>(args)...)
3558 template <
typename E>
3559 template <
typename U,
typename...Args,
typename>
3563 std::initializer_list<U> ilist,
3566 : m_failure(ilist, detail::forward<Args>(args)...)
3571 template <
typename E>
3572 template <
typename E2,
3573 typename std::enable_if<
RESULT_NS_IMPL::detail::failure_is_explicit_value_convertible<E,E2>::value,
int>::type>
3577 : m_failure(detail::forward<E2>(error))
3582 template <
typename E>
3583 template <
typename E2,
3584 typename std::enable_if<
RESULT_NS_IMPL::detail::failure_is_implicit_value_convertible<E,E2>::value,
int>::type>
3588 : m_failure(detail::forward<E2>(error))
3593 template <
typename E>
3594 template <
typename E2,
typename>
3598 : m_failure(other.error())
3603 template <
typename E>
3604 template <
typename E2,
typename>
3608 : m_failure(
static_cast<failure<E2>&&>(other).error())
3615 template <
typename E>
3616 template <
typename E2,
typename>
3624 m_failure = detail::forward<E2>(error);
3629 template <
typename E>
3630 template <
typename E2,
typename>
3636 m_failure = other.error();
3641 template <
typename E>
3642 template <
typename E2,
typename>
3648 m_failure =
static_cast<failure<E2>&&>(other).error();
3657 template <
typename E>
3660 &
noexcept ->
typename std::add_lvalue_reference<E>::
type 3665 template <
typename E>
3668 &&
noexcept ->
typename std::add_rvalue_reference<E>::
type 3670 using reference =
typename std::add_rvalue_reference<E>::type;
3672 return static_cast<reference>(m_failure);
3675 template <
typename E>
3679 ->
typename std::add_lvalue_reference<
typename std::add_const<E>::
type>::
type 3684 template <
typename E>
3688 ->
typename std::add_rvalue_reference<
typename std::add_const<E>::
type>::
type 3690 using reference =
typename std::add_rvalue_reference<
typename std::add_const<E>::type>::type;
3692 return static_cast<reference>(m_failure);
3703 template <
typename E1,
typename E2>
3705 auto RESULT_NS_IMPL::operator==(
const failure<E1>& lhs,
const failure<E2>& rhs)
3708 return lhs.error() == rhs.error();
3711 template <
typename E1,
typename E2>
3713 auto RESULT_NS_IMPL::operator!=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3716 return lhs.error() != rhs.error();
3719 template <
typename E1,
typename E2>
3721 auto RESULT_NS_IMPL::operator<(
const failure<E1>& lhs,
const failure<E2>& rhs)
3724 return lhs.error() < rhs.error();
3727 template <
typename E1,
typename E2>
3729 auto RESULT_NS_IMPL::operator>(
const failure<E1>& lhs,
const failure<E2>& rhs)
3732 return lhs.error() > rhs.error();
3735 template <
typename E1,
typename E2>
3737 auto RESULT_NS_IMPL::operator<=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3740 return lhs.error() <= rhs.error();
3743 template <
typename E1,
typename E2>
3745 auto RESULT_NS_IMPL::operator>=(
const failure<E1>& lhs,
const failure<E2>& rhs)
3748 return lhs.error() >= rhs.error();
3755 template <
typename E>
3759 -> failure<
typename std::decay<E>::
type>
3761 using result_type = failure<
typename std::decay<E>::type>;
3764 detail::forward<E>(e)
3768 template <
typename E>
3771 noexcept -> failure<E&>
3773 using result_type = failure<E&>;
3775 return result_type{e.get()};
3778 template <
typename E,
typename...Args,
typename>
3784 return failure<E>(in_place, detail::forward<Args>(args)...);
3787 template <
typename E,
typename U,
typename...Args,
typename>
3793 return failure<E>(in_place, ilist, detail::forward<Args>(args)...);
3796 template <
typename E>
3799 #if __cplusplus
>= 201703L
3808 swap(lhs.error(), rhs.error());
3819 template <
typename T,
typename E,
bool IsTrivial>
3822 ::result_union(unit)
3829 template <
typename T,
typename E,
bool IsTrivial>
3830 template <
typename...Args>
3834 noexcept(std::is_nothrow_constructible<T, Args...>::value)
3835 : m_value(detail::forward<Args>(args)...),
3840 template <
typename T,
typename E,
bool IsTrivial>
3841 template <
typename...Args>
3845 noexcept(std::is_nothrow_constructible<E, Args...>::value)
3846 : m_error(detail::forward<Args>(args)...),
3855 template <
typename T,
typename E,
bool IsTrivial>
3857 auto RESULT_NS_IMPL::detail::result_union<T, E, IsTrivial>::destroy()
3858 const noexcept ->
void 3871 template <
typename T,
typename E>
3874 ::result_union(unit)
3881 template <
typename T,
typename E>
3882 template <
typename...Args>
3886 noexcept(std::is_nothrow_constructible<T, Args...>::value)
3887 : m_value(detail::forward<Args>(args)...),
3892 template <
typename T,
typename E>
3893 template <
typename...Args>
3897 noexcept(std::is_nothrow_constructible<E, Args...>::value)
3898 : m_error(detail::forward<Args>(args)...),
3905 template <
typename T,
typename E>
3909 noexcept(std::is_nothrow_destructible<T>::value && std::is_nothrow_destructible<E>::value)
3918 template <
typename T,
typename E>
3920 auto RESULT_NS_IMPL::detail::result_union<T, E,
false>::destroy()
3924 m_value.~underlying_value_type();
3926 m_error.~underlying_error_type();
3938 template <
typename T,
typename E>
3940 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(unit)
3946 template <
typename T,
typename E>
3947 template <
typename...Args>
3949 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3952 )
noexcept(std::is_nothrow_constructible<T, Args...>::value)
3953 : storage{in_place, detail::forward<Args>(args)...}
3957 template <
typename T,
typename E>
3958 template <
typename...Args>
3960 RESULT_NS_IMPL::detail::result_construct_base<T,E>::result_construct_base(
3963 )
noexcept(std::is_nothrow_constructible<E, Args...>::value)
3964 : storage(in_place_error, detail::forward<Args>(args)...)
3972 template <
typename T,
typename E>
3973 template <
typename...Args>
3975 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value(Args&&...args)
3976 noexcept(std::is_nothrow_constructible<T,Args...>::value)
3979 using value_type =
typename storage_type::underlying_value_type;
3981 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
3982 new (p) value_type(detail::forward<Args>(args)...);
3983 storage.m_has_value =
true;
3986 template <
typename T,
typename E>
3987 template <
typename...Args>
3989 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error(Args&&...args)
3990 noexcept(std::is_nothrow_constructible<E,Args...>::value)
3993 using error_type =
typename storage_type::underlying_error_type;
3995 auto* p =
static_cast<
void*>(std::addressof(storage.m_error));
3996 new (p) error_type(detail::forward<Args>(args)...);
3997 storage.m_has_value =
false;
4000 template <
typename T,
typename E>
4001 template <
typename Result>
4003 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_error_from_result(
4007 if (other.storage.m_has_value) {
4010 construct_error(detail::forward<Result>(other).storage.m_error);
4015 template <
typename T,
typename E>
4016 template <
typename Result>
4018 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_from_result(
4022 if (other.storage.m_has_value) {
4023 construct_value_from_result_impl(
4024 std::is_lvalue_reference<T>{},
4025 detail::forward<Result>(other).storage.m_value
4028 construct_error(detail::forward<Result>(other).storage.m_error);
4032 template <
typename T,
typename E>
4033 template <
typename Value>
4035 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value(Value&& value)
4036 noexcept(std::is_nothrow_assignable<T,Value>::value)
4039 if (!storage.m_has_value) {
4041 construct_value(detail::forward<Value>(value));
4043 storage.m_value = detail::forward<Value>(value);
4047 template <
typename T,
typename E>
4048 template <
typename Error>
4050 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_error(Error&& error)
4051 noexcept(std::is_nothrow_assignable<E,Error>::value)
4054 if (storage.m_has_value) {
4056 construct_error(detail::forward<Error>(error));
4058 storage.m_error = detail::forward<Error>(error);
4062 template <
typename T,
typename E>
4063 template <
typename Result>
4065 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_from_result(Result&& other)
4068 if (other.storage.m_has_value != storage.m_has_value) {
4070 construct_from_result(detail::forward<Result>(other));
4071 }
else if (storage.m_has_value) {
4072 assign_value_from_result_impl(
4073 std::is_lvalue_reference<T>{},
4074 detail::forward<Result>(other)
4077 storage.m_error = detail::forward<Result>(other).storage.m_error;
4081 template <
typename T,
typename E>
4082 template <
typename ReferenceWrapper>
4084 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4086 ReferenceWrapper&& reference
4089 using value_type =
typename storage_type::underlying_value_type;
4091 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
4092 new (p) value_type(reference.get());
4093 storage.m_has_value =
true;
4096 template <
typename T,
typename E>
4097 template <
typename Value>
4099 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::construct_value_from_result_impl(
4102 )
noexcept(std::is_nothrow_constructible<T,Value>::value) ->
void 4104 using value_type =
typename storage_type::underlying_value_type;
4106 auto* p =
static_cast<
void*>(std::addressof(storage.m_value));
4107 new (p) value_type(detail::forward<Value>(value));
4108 storage.m_has_value =
true;
4111 template <
typename T,
typename E>
4112 template <
typename Result>
4114 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4120 storage.m_value = other.storage.m_value.get();
4123 template <
typename T,
typename E>
4124 template <
typename Result>
4126 auto RESULT_NS_IMPL::detail::result_construct_base<T,E>::assign_value_from_result_impl(
4131 storage.m_value = detail::forward<Result>(other).storage.m_value;
4139 template <
typename T,
typename E>
4142 ::result_trivial_copy_ctor_base_impl(
const result_trivial_copy_ctor_base_impl& other)
4143 noexcept(std::is_nothrow_copy_constructible<T>::value &&
4144 std::is_nothrow_copy_constructible<E>::value)
4147 using ctor_base = result_construct_base<T,E>;
4149 ctor_base::construct_from_result(
static_cast<
const ctor_base&>(other));
4156 template <
typename T,
typename E>
4159 ::result_trivial_move_ctor_base_impl(result_trivial_move_ctor_base_impl&& other)
4160 noexcept(std::is_nothrow_move_constructible<T>::value &&
4161 std::is_nothrow_move_constructible<E>::value)
4164 using ctor_base = result_construct_base<T,E>;
4166 ctor_base::construct_from_result(
static_cast<ctor_base&&>(other));
4173 template <
typename T,
typename E>
4175 auto RESULT_NS_IMPL::detail::result_trivial_copy_assign_base_impl<T, E>
4176 ::operator=(
const result_trivial_copy_assign_base_impl& other)
4177 noexcept(std::is_nothrow_copy_constructible<T>::value &&
4178 std::is_nothrow_copy_constructible<E>::value &&
4179 std::is_nothrow_copy_assignable<T>::value &&
4180 std::is_nothrow_copy_assignable<E>::value)
4181 -> result_trivial_copy_assign_base_impl&
4183 using ctor_base = result_construct_base<T,E>;
4185 ctor_base::assign_from_result(
static_cast<
const ctor_base&>(other));
4193 template <
typename T,
typename E>
4195 auto RESULT_NS_IMPL::detail::result_trivial_move_assign_base_impl<T, E>
4196 ::operator=(result_trivial_move_assign_base_impl&& other)
4197 noexcept(std::is_nothrow_move_constructible<T>::value &&
4198 std::is_nothrow_move_constructible<E>::value &&
4199 std::is_nothrow_move_assignable<T>::value &&
4200 std::is_nothrow_move_assignable<E>::value)
4201 -> result_trivial_move_assign_base_impl&
4203 using ctor_base = result_construct_base<T,E>;
4205 ctor_base::assign_from_result(
static_cast<ctor_base&&>(other));
4209 template <
typename T,
typename E>
4211 auto RESULT_NS_IMPL::detail::result_error_extractor::get(
const result<T,E>& exp)
4212 noexcept ->
const E&
4214 return exp.m_storage.storage.m_error;
4217 template <
typename T,
typename E>
4219 auto RESULT_NS_IMPL::detail::result_error_extractor::get(result<T,E>& exp)
4222 return exp.m_storage.storage.m_error;
4225 template <
typename T,
typename E>
4227 auto RESULT_NS_IMPL::detail::extract_error(
const result<T,E>& exp)
noexcept ->
const E&
4229 return result_error_extractor::get(exp);
4232 template <
typename E>
4234 auto RESULT_NS_IMPL::detail::throw_bad_result_access(E&& error) ->
void 4236 #if defined(RESULT_DISABLE_EXCEPTIONS) 4239 "error attempting to access value from result containing error\n" 4243 using exception_type = bad_result_access<
4244 typename std::remove_const<
4245 typename std::remove_reference<E>::type
4249 throw exception_type{
4250 detail::forward<E>(error)
4255 template <
typename String,
typename E>
4262 #if defined(RESULT_DISABLE_EXCEPTIONS) 4263 const auto message_string = std::string{
4264 detail::forward<String>(message)
4266 std::fprintf(stderr,
"%s\n", message_string.c_str());
4269 using exception_type = bad_result_access<
4270 typename std::remove_const<
4271 typename std::remove_reference<E>::type
4275 throw exception_type{
4276 detail::forward<String>(message),
4277 detail::forward<E>(error)
4286 template <
typename T,
typename E>
4287 template <
typename U,
typename>
4291 : m_storage(in_place)
4296 template <
typename T,
typename E>
4297 template <
typename T2,
typename E2,
4298 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_implicit_copy_convertible<T,E,T2,E2>::value,
int>::type>
4303 : m_storage(detail::unit{})
4305 m_storage.construct_from_result(
4306 static_cast<
const result<T2,E2>&>(other).m_storage
4310 template <
typename T,
typename E>
4311 template <
typename T2,
typename E2,
4312 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_explicit_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_implicit_move_convertible<T,E,T2,E2>::value,
int>::type>
4331 : m_storage(detail::unit{})
4333 m_storage.construct_from_result(
4334 static_cast<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_explicit_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
4354 template <
typename T,
typename E>
4355 template <
typename...Args,
typename>
4359 : m_storage(in_place, detail::forward<Args>(args)...)
4364 template <
typename T,
typename E>
4365 template <
typename U,
typename...Args,
typename>
4369 std::initializer_list<U> ilist,
4372 : m_storage(in_place, ilist, detail::forward<Args>(args)...)
4379 template <
typename T,
typename E>
4380 template <
typename...Args,
typename>
4384 : m_storage(in_place_error, detail::forward<Args>(args)...)
4389 template <
typename T,
typename E>
4390 template <
typename U,
typename...Args,
typename>
4394 std::initializer_list<U> ilist,
4397 : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
4404 template <
typename T,
typename E>
4405 template <
typename E2,
typename>
4409 : m_storage(in_place_error, e.error())
4414 template <
typename T,
typename E>
4415 template <
typename E2,
typename>
4419 : m_storage(in_place_error,
static_cast<E2&&>(e.error()))
4424 template <
typename T,
typename E>
4425 template <
typename U,
4426 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_explicit_value_convertible<T,U>::value,
int>::type>
4430 : m_storage(in_place, detail::forward<U>(value))
4435 template <
typename T,
typename E>
4436 template <
typename U,
4437 typename std::enable_if<
RESULT_NS_IMPL::detail::result_is_implicit_value_convertible<T,U>::value,
int>::type>
4441 : m_storage(in_place, detail::forward<U>(value))
4448 template <
typename T,
typename E>
4449 template <
typename T2,
typename E2,
typename>
4456 m_storage.assign_from_result(
4457 static_cast<
const result<T2,E2>&>(other).m_storage
4462 template <
typename T,
typename E>
4463 template <
typename T2,
typename E2,
typename>
4470 m_storage.assign_from_result(
4471 static_cast<result<T2,E2>&&>(other).m_storage
4476 template <
typename T,
typename E>
4477 template <
typename U,
typename>
4483 m_storage.assign_value(detail::forward<U>(value));
4487 template <
typename T,
typename E>
4488 template <
typename E2,
typename>
4494 m_storage.assign_error(other.error());
4498 template <
typename T,
typename E>
4499 template <
typename E2,
typename>
4505 m_storage.assign_error(
static_cast<E2&&>(other.error()));
4513 template <
typename T,
typename E>
4516 noexcept ->
typename std::remove_reference<T>::
type*
4522 #if __cplusplus
>= 201703L
4523 return std::addressof(**
this);
4529 template <
typename T,
typename E>
4532 const noexcept ->
typename std::remove_reference<
typename std::add_const<T>::
type>::
type*
4534 #if __cplusplus
>= 201703L
4535 return std::addressof(**
this);
4541 template <
typename T,
typename E>
4544 &
noexcept ->
typename std::add_lvalue_reference<T>::
type 4546 return m_storage.storage.m_value;
4549 template <
typename T,
typename E>
4552 &&
noexcept ->
typename std::add_rvalue_reference<T>::type
4554 using reference =
typename std::add_rvalue_reference<T>::type;
4556 return static_cast<reference>(m_storage.storage.m_value);
4559 template <
typename T,
typename E>
4562 const&
noexcept ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type
4564 return m_storage.storage.m_value;
4567 template <
typename T,
typename E>
4570 const&&
noexcept ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type
4572 using reference =
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
4574 return static_cast<reference>(m_storage.storage.m_value);
4579 template <
typename T,
typename E>
4584 return m_storage.storage.m_has_value;
4587 template <
typename T,
typename E>
4590 const noexcept ->
bool 4592 return m_storage.storage.m_has_value;
4595 template <
typename T,
typename E>
4598 const noexcept ->
bool 4600 return !m_storage.storage.m_has_value;
4608 #if defined(__clang__
) 4609 # pragma clang diagnostic push 4610 # pragma clang diagnostic ignored "-Wunused-value" 4611 #elif defined(__GNUC__) 4612 # pragma GCC diagnostic push 4613 # pragma GCC diagnostic ignored "-Wunused-value" 4614 #elif defined(_MSC_VER) 4617 # pragma warning(push) 4618 # pragma warning(disable:4172
) 4621 template <
typename T,
typename E>
4624 & ->
typename std::add_lvalue_reference<T>::
type 4626 return (has_value() ||
4627 (detail::throw_bad_result_access(m_storage.storage.m_error),
false),
4628 m_storage.storage.m_value
4632 template <
typename T,
typename E>
4635 && ->
typename std::add_rvalue_reference<T>::type
4637 using reference =
typename std::add_rvalue_reference<T>::type;
4639 return (has_value() ||
4640 (detail::throw_bad_result_access(
static_cast<E&&>(m_storage.storage.m_error)),
true),
4641 static_cast<reference>(m_storage.storage.m_value)
4645 template <
typename T,
typename E>
4648 const & ->
typename std::add_lvalue_reference<
typename std::add_const<T>::type>::type
4650 return (has_value() ||
4651 (detail::throw_bad_result_access(m_storage.storage.m_error),
true),
4652 m_storage.storage.m_value
4656 template <
typename T,
typename E>
4659 const && ->
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type
4661 using reference =
typename std::add_rvalue_reference<
typename std::add_const<T>::type>::type;
4663 return (has_value() ||
4664 (detail::throw_bad_result_access(
static_cast<
const E&&>(m_storage.storage.m_error)),
true),
4665 (
static_cast<reference>(m_storage.storage.m_value))
4669 #if defined(__clang__
) 4670 # pragma clang diagnostic pop 4671 #elif defined(__GNUC__) 4672 # pragma GCC diagnostic pop 4673 #elif defined(_MSC_VER) 4674 # pragma warning(pop) 4677 template <
typename T,
typename E>
4684 std::is_default_constructible<E>::value,
4685 "E must be default-constructible if 'error()' checks are used. " 4686 "This is to allow for default-constructed error states to represent the " 4690 return m_storage.storage.m_has_value
4692 : m_storage.storage.m_error;
4695 template <
typename T,
typename E>
4698 noexcept(std::is_nothrow_constructible<E>::value &&
4699 std::is_nothrow_move_constructible<E>::value) -> E
4702 std::is_default_constructible<E>::value,
4703 "E must be default-constructible if 'error()' checks are used. " 4704 "This is to allow for default-constructed error states to represent the " 4708 return m_storage.storage.m_has_value
4710 :
static_cast<E&&>(m_storage.storage.m_error);
4715 template <
typename T,
typename E>
4716 template <
typename String,
typename>
4722 detail::throw_bad_result_access_message(
4723 detail::forward<String>(message),
4724 m_storage.storage.m_error
4729 template <
typename T,
typename E>
4730 template <
typename String,
typename>
4736 detail::throw_bad_result_access_message(
4737 detail::forward<String>(message),
4738 static_cast<E&&>(m_storage.storage.m_error)
4747 template <
typename T,
typename E>
4748 template <
typename U>
4751 const& ->
typename std::remove_reference<T>::
type 4753 return m_storage.storage.m_has_value
4754 ? m_storage.storage.m_value
4755 : detail::forward<U>(default_value);
4758 template <
typename T,
typename E>
4759 template <
typename U>
4762 && ->
typename std::remove_reference<T>::type
4764 return m_storage.storage.m_has_value
4765 ?
static_cast<T&&>(**
this)
4766 : detail::forward<U>(default_value);
4769 template <
typename T,
typename E>
4770 template <
typename U>
4773 const& -> error_type
4775 return m_storage.storage.m_has_value
4776 ? detail::forward<U>(default_error)
4777 : m_storage.storage.m_error;
4780 template <
typename T,
typename E>
4781 template <
typename U>
4786 return m_storage.storage.m_has_value
4787 ? detail::forward<U>(default_error)
4788 :
static_cast<E&&>(m_storage.storage.m_error);
4791 template <
typename T,
typename E>
4792 template <
typename U>
4795 const -> result<
typename std::decay<U>::type,E>
4797 return map([&value](
const T&){
4798 return detail::forward<U>(value);
4804 template <
typename T,
typename E>
4805 template <
typename Fn>
4808 const & -> detail::invoke_result_t<Fn,
const T&>
4810 using result_type = detail::invoke_result_t<Fn,
const T&>;
4814 "flat_map must return a result type or the program is ill-formed" 4818 ? detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value)
4819 : result_type(in_place_error, m_storage.storage.m_error);
4822 template <
typename T,
typename E>
4823 template <
typename Fn>
4826 && -> detail::invoke_result_t<Fn, T&&>
4828 using result_type = detail::invoke_result_t<Fn, T&&>;
4832 "flat_map must return a result type or the program is ill-formed" 4836 ? detail::invoke(detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value))
4837 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
4840 template <
typename T,
typename E>
4841 template <
typename Fn>
4844 const & -> result<detail::invoke_result_t<Fn,
const T&>,E>
4846 using result_type = detail::invoke_result_t<Fn,
const T&>;
4848 return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
4851 template <
typename T,
typename E>
4852 template <
typename Fn>
4855 && -> result<detail::invoke_result_t<Fn,T&&>,E>
4857 using result_type = detail::invoke_result_t<Fn,T&&>;
4859 return static_cast<result<T,E>&&>(*
this).map_impl(
4860 std::is_void<result_type>{},
4861 detail::forward<Fn>(fn)
4867 template <
typename T,
typename E>
4868 template <
typename Fn>
4871 const & -> result<T, detail::invoke_result_t<Fn,
const E&>>
4873 using result_type = result<T, detail::invoke_result_t<Fn,
const E&>>;
4876 ? result_type(in_place_error, detail::invoke(
4877 detail::forward<Fn>(fn), m_storage.storage.m_error
4879 : result_type(in_place, m_storage.storage.m_value);
4882 template <
typename T,
typename E>
4883 template <
typename Fn>
4886 && -> result<T, detail::invoke_result_t<Fn,E&&>>
4888 using result_type = result<T, detail::invoke_result_t<Fn, E&&>>;
4891 ? result_type(in_place_error, detail::invoke(
4892 detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error)
4894 : result_type(
static_cast<T&&>(m_storage.storage.m_value));
4897 template <
typename T,
typename E>
4898 template <
typename Fn>
4901 const & -> detail::invoke_result_t<Fn,
const E&>
4903 using result_type = detail::invoke_result_t<Fn,
const E&>;
4907 "flat_map_error must return a result type or the program is ill-formed" 4911 ? result_type(in_place, m_storage.storage.m_value)
4912 : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
4915 template <
typename T,
typename E>
4916 template <
typename Fn>
4919 && -> detail::invoke_result_t<Fn, E&&>
4921 using result_type = detail::invoke_result_t<Fn, E&&>;
4925 "flat_map_error must return a result type or the program is ill-formed" 4929 ? result_type(in_place,
static_cast<T&&>(m_storage.storage.m_value))
4930 : detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error));
4937 template <
typename T,
typename E>
4938 template <
typename Fn>
4940 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4941 const & -> result<
void,E>
4943 using result_type = result<
void, E>;
4946 ? (detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_value), result_type{})
4947 : result_type(in_place_error, m_storage.storage.m_error);
4950 template <
typename T,
typename E>
4951 template <
typename Fn>
4953 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
4954 const & -> result<detail::invoke_result_t<Fn,
const T&>,E>
4956 using invoke_result_type = detail::invoke_result_t<Fn,
const T&>;
4957 using result_type = result<invoke_result_type, E>;
4960 ? result_type(in_place, detail::invoke(
4961 detail::forward<Fn>(fn), m_storage.storage.m_value
4963 : result_type(in_place_error, m_storage.storage.m_error);
4966 template <
typename T,
typename E>
4967 template <
typename Fn>
4969 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::true_type, Fn&& fn)
4970 && -> result<
void,E>
4972 using result_type = result<
void, E>;
4976 detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value)
4978 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
4981 template <
typename T,
typename E>
4982 template <
typename Fn>
4984 auto RESULT_NS_IMPL::result<T, E>::map_impl(std::false_type, Fn&& fn)
4985 && -> result<detail::invoke_result_t<Fn,T&&>,E>
4987 using invoke_result_type = detail::invoke_result_t<Fn,T&&>;
4988 using result_type = result<invoke_result_type, E>;
4991 ? result_type(in_place, detail::invoke(
4992 detail::forward<Fn>(fn),
static_cast<T&&>(m_storage.storage.m_value)
4994 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5005 template <
typename E>
5009 : m_storage(in_place)
5014 template <
typename E>
5015 template <
typename U,
typename E2,
typename>
5019 : m_storage(detail::unit{})
5021 m_storage.construct_error_from_result(
5022 static_cast<
const result<U,E2>&>(other).m_storage
5026 template <
typename E>
5027 template <
typename U,
typename E2,
typename>
5031 : m_storage(detail::unit{})
5033 m_storage.construct_error_from_result(
5034 static_cast<result<U,E2>&&>(other).m_storage
5041 template <
typename E>
5045 : m_storage(in_place)
5050 template <
typename E>
5051 template <
typename...Args,
typename>
5055 : m_storage(in_place_error, detail::forward<Args>(args)...)
5060 template <
typename E>
5061 template <
typename U,
typename...Args,
typename>
5064 std::initializer_list<U> ilist,
5067 : m_storage(in_place_error, ilist, detail::forward<Args>(args)...)
5074 template <
typename E>
5075 template <
typename E2,
typename>
5079 : m_storage(in_place_error, e.error())
5084 template <
typename E>
5085 template <
typename E2,
typename>
5089 : m_storage(in_place_error,
static_cast<E2&&>(e.error()))
5096 template <
typename E>
5097 template <
typename E2,
typename>
5103 m_storage.assign_from_result(other.m_storage);
5107 template <
typename E>
5108 template <
typename E2,
typename>
5114 m_storage.assign_from_result(
static_cast<result<
void,E2>&&>(other).m_storage);
5118 template <
typename E>
5119 template <
typename E2,
typename>
5125 m_storage.assign_error(other.error());
5129 template <
typename E>
5130 template <
typename E2,
typename>
5136 m_storage.assign_error(
static_cast<E2&&>(other.error()));
5144 template <
typename E>
5152 template <
typename E>
5155 const noexcept ->
bool 5157 return m_storage.storage.m_has_value;
5160 template <
typename E>
5163 const noexcept ->
bool 5170 template <
typename E>
5177 (detail::throw_bad_result_access(m_storage.storage.m_error),
true)
5181 template <
typename E>
5188 (detail::throw_bad_result_access(
static_cast<E&&>(m_storage.storage.m_error)),
true)
5192 template <
typename E>
5199 return has_value() ? E{} : m_storage.storage.m_error;
5202 template <
typename E>
5208 return has_value() ? E{} :
static_cast<E&&>(m_storage.storage.m_error);
5213 template <
typename E>
5214 template <
typename String,
typename>
5220 detail::throw_bad_result_access_message(
5221 detail::forward<String>(message),
5222 m_storage.storage.m_error
5227 template <
typename E>
5228 template <
typename String,
typename>
5234 detail::throw_bad_result_access_message(
5235 detail::forward<String>(message),
5236 static_cast<E&&>(m_storage.storage.m_error)
5245 template <
typename E>
5246 template <
typename U>
5249 const & -> error_type
5252 ? detail::forward<U>(default_error)
5253 : m_storage.storage.m_error;
5256 template <
typename E>
5257 template <
typename U>
5263 ? detail::forward<U>(default_error)
5264 :
static_cast<E&&>(m_storage.storage.m_error);
5267 template <
typename E>
5268 template <
typename U>
5271 const -> result<
typename std::decay<U>::
type,E>
5273 return map([&value]{
5274 return detail::forward<U>(value);
5280 template <
typename E>
5281 template <
typename Fn>
5284 const & -> detail::invoke_result_t<Fn>
5286 using result_type = detail::invoke_result_t<Fn>;
5290 "flat_map must return a result type or the program is ill-formed" 5294 ? detail::invoke(detail::forward<Fn>(fn))
5295 : result_type(in_place_error, m_storage.storage.m_error);
5298 template <
typename E>
5299 template <
typename Fn>
5302 && -> detail::invoke_result_t<Fn>
5304 using result_type = detail::invoke_result_t<Fn>;
5308 "flat_map must return a result type or the program is ill-formed" 5312 ? detail::invoke(detail::forward<Fn>(fn))
5313 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5316 template <
typename E>
5317 template <
typename Fn>
5320 const & -> result<detail::invoke_result_t<Fn>,E>
5322 using result_type = detail::invoke_result_t<Fn>;
5324 return map_impl(std::is_void<result_type>{}, detail::forward<Fn>(fn));
5327 template <
typename E>
5328 template <
typename Fn>
5331 && -> result<detail::invoke_result_t<Fn>,E>
5333 using result_type = detail::invoke_result_t<Fn>;
5335 return static_cast<result<
void,E>&&>(*
this).map_impl(
5336 std::is_void<result_type>{},
5337 detail::forward<Fn>(fn)
5343 template <
typename E>
5344 template <
typename Fn>
5347 const & -> result<
void, detail::invoke_result_t<Fn,
const E&>>
5349 using result_type = result<
void, detail::invoke_result_t<Fn,
const E&>>;
5353 : result_type(in_place_error, detail::invoke(
5354 detail::forward<Fn>(fn), m_storage.storage.m_error
5358 template <
typename E>
5359 template <
typename Fn>
5362 && -> result<
void, detail::invoke_result_t<Fn,E&&>>
5364 using result_type = result<
void, detail::invoke_result_t<Fn, E&&>>;
5368 : result_type(in_place_error,
5369 detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error)
5373 template <
typename E>
5374 template <
typename Fn>
5377 const & -> detail::invoke_result_t<Fn,
const E&>
5379 using result_type = detail::invoke_result_t<Fn,
const E&>;
5383 "flat_map_error must return a result type or the program is ill-formed" 5386 std::is_default_constructible<
typename result_type::value_type>::value,
5387 "flat_map_error for result<void,E> requires the new T type to be default-" 5393 : detail::invoke(detail::forward<Fn>(fn), m_storage.storage.m_error);
5396 template <
typename E>
5397 template <
typename Fn>
5400 && -> detail::invoke_result_t<Fn,E&&>
5402 using result_type = detail::invoke_result_t<Fn,E&&>;
5406 "flat_map_error must return a result type or the program is ill-formed" 5409 std::is_default_constructible<
typename result_type::value_type>::value,
5410 "flat_map_error for result<void,E> requires the new T type to be default-" 5416 : detail::invoke(detail::forward<Fn>(fn),
static_cast<E&&>(m_storage.storage.m_error));
5423 template <
typename E>
5424 template <
typename Fn>
5426 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::true_type, Fn&& fn)
5427 const & -> result<
void,E>
5429 using result_type = result<
void, E>;
5432 ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5433 : result_type(in_place_error, m_storage.storage.m_error);
5436 template <
typename E>
5437 template <
typename Fn>
5439 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::false_type, Fn&& fn)
5440 const & -> result<detail::invoke_result_t<Fn>,E>
5442 using invoke_result_type = detail::invoke_result_t<Fn>;
5443 using result_type = result<invoke_result_type, E>;
5446 ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5447 : result_type(in_place_error, m_storage.storage.m_error);
5450 template <
typename E>
5451 template <
typename Fn>
5453 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::true_type, Fn&& fn)
5454 && -> result<
void,E>
5456 using result_type = result<
void, E>;
5459 ? (detail::invoke(detail::forward<Fn>(fn)), result_type{})
5460 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5463 template <
typename E>
5464 template <
typename Fn>
5466 auto RESULT_NS_IMPL::result<
void, E>::map_impl(std::false_type, Fn&& fn)
5467 && -> result<detail::invoke_result_t<Fn>,E>
5469 using invoke_result_type = detail::invoke_result_t<Fn>;
5470 using result_type = result<invoke_result_type, E>;
5473 ? result_type(in_place, detail::invoke(detail::forward<Fn>(fn)))
5474 : result_type(in_place_error,
static_cast<E&&>(m_storage.storage.m_error));
5485 template <
typename T1,
typename E1,
typename T2,
typename E2>
5488 const result<T2,E2>& rhs)
5491 return (lhs.has_value() == rhs.has_value())
5495 : detail::extract_error(lhs) == detail::extract_error(rhs)
5500 template <
typename T1,
typename E1,
typename T2,
typename E2>
5503 const result<T2,E2>& rhs)
5506 return (lhs.has_value() == rhs.has_value())
5510 : detail::extract_error(lhs) != detail::extract_error(rhs)
5515 template <
typename T1,
typename E1,
typename T2,
typename E2>
5518 const result<T2,E2>& rhs)
5521 return (lhs.has_value() == rhs.has_value())
5525 : detail::extract_error(lhs) >= detail::extract_error(rhs)
5527 :
static_cast<
int>(
static_cast<
bool>(lhs)) >=
static_cast<
int>(
static_cast<
bool>(rhs));
5530 template <
typename T1,
typename E1,
typename T2,
typename E2>
5533 const result<T2,E2>& rhs)
5536 return (lhs.has_value() == rhs.has_value())
5540 : detail::extract_error(lhs) <= detail::extract_error(rhs)
5542 :
static_cast<
int>(
static_cast<
bool>(lhs)) <=
static_cast<
int>(
static_cast<
bool>(rhs));
5545 template <
typename T1,
typename E1,
typename T2,
typename E2>
5548 const result<T2,E2>& rhs)
5551 return (lhs.has_value() == rhs.has_value())
5555 : detail::extract_error(lhs) > detail::extract_error(rhs)
5557 :
static_cast<
int>(
static_cast<
bool>(lhs)) >
static_cast<
int>(
static_cast<
bool>(rhs));
5560 template <
typename T1,
typename E1,
typename T2,
typename E2>
5563 const result<T2,E2>& rhs)
5566 return (lhs.has_value() == rhs.has_value())
5570 : detail::extract_error(lhs) < detail::extract_error(rhs)
5572 :
static_cast<
int>(
static_cast<
bool>(lhs)) <
static_cast<
int>(
static_cast<
bool>(rhs));
5578 template <
typename E1,
typename E2>
5581 const result<
void,E2>& rhs)
5584 return lhs.has_value() == rhs.has_value()
5588 : detail::extract_error(lhs) == detail::extract_error(rhs)
5593 template <
typename E1,
typename E2>
5596 const result<
void,E2>& rhs)
5599 return lhs.has_value() == rhs.has_value()
5603 : detail::extract_error(lhs) != detail::extract_error(rhs)
5608 template <
typename E1,
typename E2>
5611 const result<
void,E2>& rhs)
5614 return lhs.has_value() == rhs.has_value()
5618 : detail::extract_error(lhs) >= detail::extract_error(rhs)
5620 :
static_cast<
int>(
static_cast<
bool>(lhs)) >=
static_cast<
int>(
static_cast<
bool>(rhs));
5623 template <
typename E1,
typename E2>
5626 const result<
void,E2>& rhs)
5629 return lhs.has_value() == rhs.has_value()
5633 : detail::extract_error(lhs) <= detail::extract_error(rhs)
5635 :
static_cast<
int>(
static_cast<
bool>(lhs)) <=
static_cast<
int>(
static_cast<
bool>(rhs));
5638 template <
typename E1,
typename E2>
5641 const result<
void,E2>& rhs)
5644 return lhs.has_value() == rhs.has_value()
5648 : detail::extract_error(lhs) > detail::extract_error(rhs)
5650 :
static_cast<
int>(
static_cast<
bool>(lhs)) >
static_cast<
int>(
static_cast<
bool>(rhs));
5653 template <
typename E1,
typename E2>
5656 const result<
void,E2>& rhs)
5659 return lhs.has_value() == rhs.has_value()
5663 : detail::extract_error(lhs) < detail::extract_error(rhs)
5665 :
static_cast<
int>(
static_cast<
bool>(lhs)) <
static_cast<
int>(
static_cast<
bool>(rhs));
5671 template <
typename T,
typename E,
typename U,
typename>
5673 auto RESULT_NS_IMPL::operator==(
const result<T,E>& exp,
const U& value)
5676 return (exp.has_value() && *exp == value);
5679 template <
typename T,
typename U,
typename E,
typename>
5681 auto RESULT_NS_IMPL::operator==(
const T& value,
const result<U,E>& exp)
5684 return (exp.has_value() && *exp == value);
5687 template <
typename T,
typename E,
typename U,
typename>
5689 auto RESULT_NS_IMPL::operator!=(
const result<T,E>& exp,
const U& value)
5692 return exp.has_value() ? *exp != value :
true;
5695 template <
typename T,
typename U,
typename E,
typename>
5697 auto RESULT_NS_IMPL::operator!=(
const T& value,
const result<U,E>& exp)
5700 return exp.has_value() ? value != *exp :
true;
5703 template <
typename T,
typename E,
typename U,
typename>
5705 auto RESULT_NS_IMPL::operator<=(
const result<T,E>& exp,
const U& value)
5708 return exp.has_value() ? *exp <= value :
false;
5711 template <
typename T,
typename U,
typename E,
typename>
5713 auto RESULT_NS_IMPL::operator<=(
const T& value,
const result<U,E>& exp)
5716 return exp.has_value() ? value <= *exp :
true;
5719 template <
typename T,
typename E,
typename U,
typename>
5721 auto RESULT_NS_IMPL::operator>=(
const result<T,E>& exp,
const U& value)
5724 return exp.has_value() ? *exp >= value :
true;
5727 template <
typename T,
typename U,
typename E,
typename>
5729 auto RESULT_NS_IMPL::operator>=(
const T& value,
const result<U,E>& exp)
5732 return exp.has_value() ? value >= *exp :
false;
5735 template <
typename T,
typename E,
typename U,
typename>
5737 auto RESULT_NS_IMPL::operator<(
const result<T,E>& exp,
const U& value)
5740 return exp.has_value() ? *exp < value :
false;
5743 template <
typename T,
typename U,
typename E,
typename>
5745 auto RESULT_NS_IMPL::operator<(
const T& value,
const result<U,E>& exp)
5748 return exp.has_value() ? value < *exp :
true;
5751 template <
typename T,
typename E,
typename U,
typename>
5753 auto RESULT_NS_IMPL::operator>(
const result<T,E>& exp,
const U& value)
5756 return exp.has_value() ? *exp > value :
false;
5759 template <
typename T,
typename U,
typename E,
typename>
5761 auto RESULT_NS_IMPL::operator>(
const T& value,
const result<U,E>& exp)
5764 return exp.has_value() ? value > *exp :
true;
5769 template <
typename T,
typename E,
typename U>
5771 auto RESULT_NS_IMPL::operator==(
const result<T,E>& exp,
const failure<U>& error)
5774 return exp.has_error() ? detail::extract_error(exp) == error.error() :
false;
5777 template <
typename T,
typename U,
typename E>
5779 auto RESULT_NS_IMPL::operator==(
const failure<T>& error,
const result<E,U>& exp)
5782 return exp.has_error() ? error.error() == detail::extract_error(exp) :
false;
5785 template <
typename T,
typename E,
typename U>
5787 auto RESULT_NS_IMPL::operator!=(
const result<T,E>& exp,
const failure<U>& error)
5790 return exp.has_error() ? detail::extract_error(exp) != error.error() :
true;
5793 template <
typename T,
typename U,
typename E>
5795 auto RESULT_NS_IMPL::operator!=(
const failure<T>& error,
const result<E,U>& exp)
5798 return exp.has_error() ? error.error() != detail::extract_error(exp) :
true;
5801 template <
typename T,
typename E,
typename U>
5803 auto RESULT_NS_IMPL::operator<=(
const result<T,E>& exp,
const failure<U>& error)
5806 return exp.has_error() ? detail::extract_error(exp) <= error.error() :
true;
5809 template <
typename T,
typename U,
typename E>
5811 auto RESULT_NS_IMPL::operator<=(
const failure<T>& error,
const result<E,U>& exp)
5814 return exp.has_error() ? error.error() <= detail::extract_error(exp) :
false;
5817 template <
typename T,
typename E,
typename U>
5819 auto RESULT_NS_IMPL::operator>=(
const result<T,E>& exp,
const failure<U>& error)
5822 return exp.has_error() ? detail::extract_error(exp) >= error.error() :
false;
5825 template <
typename T,
typename U,
typename E>
5827 auto RESULT_NS_IMPL::operator>=(
const failure<T>& error,
const result<E,U>& exp)
5830 return exp.has_error() ? error.error() >= detail::extract_error(exp) :
true;
5833 template <
typename T,
typename E,
typename U>
5835 auto RESULT_NS_IMPL::operator<(
const result<T,E>& exp,
const failure<U>& error)
5838 return exp.has_error() ? detail::extract_error(exp) < error.error() :
true;
5841 template <
typename T,
typename U,
typename E>
5843 auto RESULT_NS_IMPL::operator<(
const failure<T>& error,
const result<E,U>& exp)
5846 return exp.has_error() ? error.error() < detail::extract_error(exp) :
false;
5849 template <
typename T,
typename E,
typename U>
5851 auto RESULT_NS_IMPL::operator>(
const result<T,E>& exp,
const failure<U>& error)
5854 return exp.has_error() ? detail::extract_error(exp) > error.error() :
false;
5857 template <
typename T,
typename U,
typename E>
5859 auto RESULT_NS_IMPL::operator>(
const failure<T>& error,
const result<E,U>& exp)
5862 return exp.has_error() ? error.error() > detail::extract_error(exp) :
true;
5869 template <
typename T,
typename E>
5872 #if __cplusplus
>= 201703L
5885 if (lhs.has_value() == rhs.has_value()) {
5886 if (lhs.has_value()) {
5889 auto& lhs_error = detail::result_error_extractor::get(lhs);
5890 auto& rhs_error = detail::result_error_extractor::get(rhs);
5892 swap(lhs_error, rhs_error);
5896 auto temp =
static_cast<result<T,E>&&>(lhs);
5897 lhs =
static_cast<result<T,E>&&>(rhs);
5898 rhs =
static_cast<result<T,E>&&>(temp);
5902 template <
typename E>
5905 #if __cplusplus
>= 201703L
5917 if (lhs.has_value() == rhs.has_value()) {
5918 if (lhs.has_error()) {
5919 auto& lhs_error = detail::result_error_extractor::get(lhs);
5920 auto& rhs_error = detail::result_error_extractor::get(rhs);
5922 swap(lhs_error, rhs_error);
5926 auto temp =
static_cast<result<
void,E>&&>(lhs);
5927 lhs =
static_cast<result<
void,E>&&>(rhs);
5928 rhs =
static_cast<result<
void,E>&&>(temp);
5932 #if defined(__clang__
) 5933 # pragma clang diagnostic pop 5936 #undef RESULT_NAMESPACE_INTERNAL 5937 #undef RESULT_NS_IMPL 5938 #undef RESULT_CPP14_CONSTEXPR 5939 #undef RESULT_CPP17_INLINE 5940 #undef RESULT_INLINE_VISIBILITY 5941 #undef RESULT_NODISCARD 5942 #undef RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error() &noexcept -> typename std::add_lvalue_reference< E >::type
Gets the underlying error.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator->() noexcept -> typename std::remove_reference< T >::type *
Retrieves a pointer to the contained value.
constexpr failure(E2 &&error) noexcept(std::is_nothrow_constructible< E, E2 >::value)
Constructs a failure from the given error.
RESULT_WARN_UNUSED constexpr auto fail(Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value) -> failure< E >
Constructs a failure type from a series of arguments.
constexpr result(in_place_t) noexcept
Constructs a result object in a value state.
bad_result_access(E2 &&error)
Constructs this exception using the underlying error type for the error type.
failure(failure &&other)=default
Constructs this failure by moving the contents of an existing one.
constexpr result(result &&other)=default
Move constructs a result.
RESULT_WARN_UNUSED constexpr auto fail(E &&e) noexcept(std::is_nothrow_constructible< typename std::decay< E >::type, E >::value) -> failure< typename std::decay< E >::type >
Deduces and constructs a failure type from e.
auto error() &&noexcept -> E &&
Gets the underlying error.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error() &&noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_copy_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value. ...
constexpr result() noexcept(std::is_nothrow_constructible< U >::value)
Default-constructs a result with the underlying value type active.
RESULT_WARN_UNUSED constexpr auto flat_map_error(Fn &&fn) const &-> detail::invoke_result_t< Fn, const E &>
Invokes the function fn with the error of this result as the argument.
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an error.
RESULT_WARN_UNUSED constexpr auto map(Fn &&fn) const &-> result< detail::invoke_result_t< Fn >, E >
Invokes the function fn if (*this) contains no value.
RESULT_WARN_UNUSED constexpr auto has_value() const noexcept -> bool
Returns true if *this contains a value.
auto operator=(const result< T2, E2 > &other) noexcept(std::is_nothrow_assignable< T, const T2 &>::value &&std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Copy-converts the state of other.
constexpr result() noexcept
Constructs a result object in a value state.
constexpr result(const result &other)=default
Copy constructs this result.
constexpr result(in_place_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< T, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains a value.
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Perfect-forwarded assignment.
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs the underlying error of this result.
#define RESULT_CPP17_INLINE
constexpr result(const result &other)=default
Copy constructs this result.
#define RESULT_WARN_UNUSED
constexpr result(in_place_error_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains an error.
constexpr result(in_place_t, Args &&... args) noexcept(std::is_nothrow_constructible< T, Args... >::value)
Constructs a result object that contains a value.
auto error() const &noexcept -> const E &
Gets the underlying error.
RESULT_WARN_UNUSED constexpr auto has_error() const noexcept -> bool
Returns true if *this contains an error.
auto operator=(U &&value) noexcept(std::is_nothrow_assignable< T, U >::value) -> result &
Perfect-forwarded assignment.
A structure for representing in-place construction of an error type.
auto swap(result< void, E > &lhs, result< void, E > &rhs) noexcept(std::is_nothrow_move_constructible< result< void, E >>::value &&std::is_nothrow_move_assignable< result< void, E >>::value) -> void
Swaps the contents of lhs with rhs.
RESULT_WARN_UNUSED constexpr auto and_then(U &&value) const -> result< typename std::decay< U >::type, E >
Returns a result containing value if this result contains a value, otherwise returns a result contain...
RESULT_WARN_UNUSED constexpr operator bool() const noexcept
Contextually convertible to true if *this does not contain an error.
RESULT_WARN_UNUSED constexpr auto error_or(U &&default_error) const &-> error_type
Returns the contained error if *this has an error, otherwise returns default_error.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value_or(U &&default_value) &&-> typename std::remove_reference< T >::type
Returns the contained value if *this has a value, otherwise returns default_value.
constexpr result(in_place_error_t, Args &&... args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a result object that contains an error.
constexpr auto map_error(Fn &&fn) const &-> result< void, detail::invoke_result_t< Fn, const E &>>
Invokes the function fn with the error of this result as the argument.
RESULT_WARN_UNUSED constexpr auto flat_map(Fn &&fn) const &-> detail::invoke_result_t< Fn >
Invokes the function fn if (*this) contains no value.
result(result< U, E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Converting move constructor.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto map(Fn &&fn) &&-> result< detail::invoke_result_t< Fn >, E >
Invokes the function fn if (*this) contains no value.
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
result(const result< U, E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Converting copy constructor.
result(result< T2, E2 > &&other) noexcept(std::is_nothrow_constructible< T, T2 &&>::value &&std::is_nothrow_constructible< E, E2 &&>::value)
Converting move constructor.
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs the underlying error of this result.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error() &&noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_move_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value. ...
auto operator=(const failure &other) -> failure &=default
Assigns the contents of other to this by copy-assignment.
bad_result_access(const char *what_arg, E2 &&error)
Constructs this exception using the underlying error type for the error and a message.
RESULT_CPP14_CONSTEXPR auto operator=(E2 &&error) noexcept(std::is_nothrow_assignable< E, E2 >::value||std::is_lvalue_reference< E >::value) -> failure &
Assigns the value of error to this failure through move-assignment.
auto swap(result< T, E > &lhs, result< T, E > &rhs) noexcept(std::is_nothrow_move_constructible< result< T, E >>::value &&std::is_nothrow_move_assignable< result< T, E >>::value) -> void
Swaps the contents of lhs with rhs.
auto operator=(const result< void, E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Copy-converts the state of other.
RESULT_CPP14_CONSTEXPR auto error() &&noexcept -> typename std::add_rvalue_reference< E >::type
Gets the underlying error.
bad_result_access(const std::string &what_arg, E2 &&error)
Constructs this exception using the underlying error type for the error and a message.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map_error(Fn &&fn) &&-> detail::invoke_result_t< Fn, E &&>
Invokes the function fn with the error of this result as the argument.
RESULT_CPP14_CONSTEXPR auto value() &&-> void
Throws an exception if (*this) is in an error state.
constexpr result(in_place_error_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a result object that contains an error.
auto operator=(failure &&other) -> failure &=default
Assigns the contents of other to this by move-assignment.
constexpr result(failure< E2 > &&e) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs the underlying error of this result.
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Perfect-forwarded assignment.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto operator*() &noexcept -> typename std::add_lvalue_reference< T >::type
Retrieves a reference to the contained value.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto value() &&-> typename std::add_rvalue_reference< T >::type
Returns a reference to the contained value.
A structure for representing in-place construction.
RESULT_CPP14_CONSTEXPR auto expect(String &&message) const &-> void
}
#define RESULT_NAMESPACE_INTERNAL
RESULT_CPP14_CONSTEXPR auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> failure &
Assigns the contents of other to this by move conversion.
auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> result &
Perfect-forwarded assignment.
RESULT_CPP14_CONSTEXPR auto map_error(Fn &&fn) &&-> result< void, detail::invoke_result_t< Fn, E &&>>
Invokes the function fn with the error of this result as the argument.
auto error() &noexcept -> E &
Gets the underlying error.
#define RESULT_INLINE_VISIBILITY
constexpr failure(failure< E2 > &&other) noexcept(std::is_nothrow_constructible< E, E2 &&>::value)
Constructs this failure by move-converting other.
RESULT_CPP14_CONSTEXPR auto value() const &-> void
Throws an exception if (*this) is in an error state.
auto operator=(result &&other) -> result &=default
Move assigns the result stored in other.
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
RESULT_WARN_UNUSED constexpr auto fail(std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value) -> failure< E >
Constructs a failure type from an initializer list and series of arguments.
RESULT_CPP14_CONSTEXPR auto expect(String &&message) &&-> void
}
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto flat_map(Fn &&fn) &&-> detail::invoke_result_t< Fn >
Invokes the function fn if (*this) contains no value.
constexpr auto error() const &noexcept -> typename std::add_lvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
constexpr result(result &&other)=default
Move constructs a result.
auto error() const &&noexcept -> const E &&
Gets the underlying error.
auto swap(failure< E > &lhs, failure< E > &rhs) noexcept(std::is_nothrow_move_constructible< E >::value) -> void
Swaps the contents of two failure values.
auto operator=(result< void, E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Move-converts the state of other.
constexpr result(U &&value) noexcept(std::is_nothrow_constructible< T, U >::value)
Constructs a result object that contains a value.
RESULT_CPP14_CONSTEXPR auto operator=(const failure< E2 > &other) noexcept(std::is_nothrow_assignable< E, const E2 &>::value) -> failure &
Assigns the contents of other to this by copy conversion.
auto operator=(const result &other) -> result &=default
Copy assigns the result stored in other.
RESULT_WARN_UNUSED RESULT_CPP14_CONSTEXPR auto error_or(U &&default_error) &&-> error_type
Returns the contained error if *this has an error, otherwise returns default_error.
RESULT_WARN_UNUSED constexpr auto error() const &noexcept(std::is_nothrow_constructible< E >::value &&std::is_nothrow_copy_constructible< E >::value) -> E
Returns the contained error, if one exists, or a default-constructed error value. ...
RESULT_WARN_UNUSED constexpr auto fail(std::reference_wrapper< E > e) noexcept -> failure< E &>
Deduces a failure reference from a reverence_wrapper.
constexpr failure(in_place_t, std::initializer_list< U > ilist, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U >, Args... >::value)
Constructs a failure by delegating construction to the underlying constructor.
auto operator=(result< T2, E2 > &&other) noexcept(std::is_nothrow_assignable< T, T2 &&>::value &&std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Move-converts the state of other.
RESULT_WARN_UNUSED constexpr auto operator->() const noexcept -> typename std::remove_reference< typename std::add_const< T >::type >::type *
Retrieves a pointer to the contained value.
result(const result< T2, E2 > &other) noexcept(std::is_nothrow_constructible< T, const T2 &>::value &&std::is_nothrow_constructible< E, const E2 &>::value)
Converting copy constructor.
constexpr auto error() const &&noexcept -> typename std::add_rvalue_reference< typename std::add_const< E >::type >::type
Gets the underlying error.
constexpr failure(in_place_t, Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Constructs a failure by delegating construction to the underlying constructor.
failure()=default
Constructs a failure via default construction.
failure(const failure &other)=default
Constructs this failure by copying the contents of an existing one.
constexpr failure(const failure< E2 > &other) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs this failure by copy-converting other.
constexpr result(const failure< E2 > &e) noexcept(std::is_nothrow_constructible< E, const E2 &>::value)
Constructs the underlying error of this result.
#define RESULT_CPP14_CONSTEXPR
auto operator=(failure< E2 > &&other) noexcept(std::is_nothrow_assignable< E, E2 &&>::value) -> result &
Perfect-forwarded assignment.