25#ifndef GUL17_EXPECTED_H_
26#define GUL17_EXPECTED_H_
92template <
typename T,
typename E>
105#if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
106#define GUL17_EXPECTED_EXCEPTIONS_ENABLED
109#if (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
110#ifndef GUL17_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
111#define GUL17_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
115 : std::is_trivially_copy_constructible<T> {};
116#ifdef _GLIBCXX_VECTOR
117template <
class T,
class A>
123#define GUL17_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
124 gul17::detail::is_trivially_copy_constructible<T>
125#define GUL17_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
126 std::is_trivially_copy_assignable<T>
127#define GUL17_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
128 std::is_trivially_destructible<T>
130#define GUL17_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
131 std::is_trivially_copy_constructible<T>
132#define GUL17_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
133 std::is_trivially_copy_assignable<T>
134#define GUL17_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
135 std::is_trivially_destructible<T>
138template <
class T,
class E>
class expected;
144 static_assert(!std::is_same<E, void>::value,
"E must not be void");
146 unexpected() =
delete;
147 constexpr explicit unexpected(
const E &
e) :
m_val(
e) {}
149 constexpr explicit unexpected(
E &&
e) :
m_val(std::
move(
e)) {}
151 template <
class...
Args,
typename std::enable_if<std::is_constructible<
153 constexpr explicit unexpected(
Args &&...
args)
156 class U,
class...
Args,
157 typename std::enable_if<std::is_constructible<
158 E, std::initializer_list<U> &,
Args &&...>
::value>::type * =
nullptr>
159 constexpr explicit unexpected(std::initializer_list<U>
l,
Args &&...
args)
164 constexpr E &&
value() && {
return std::move(
m_val); }
171#ifdef __cpp_deduction_guides
177 return lhs.value() ==
rhs.value();
181 return lhs.value() !=
rhs.value();
185 return lhs.value() <
rhs.value();
189 return lhs.value() <=
rhs.value();
193 return lhs.value() >
rhs.value();
197 return lhs.value() >=
rhs.value();
213#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
214 throw std::forward<E>(
e);
230template <
class T> tag
swap(T &, T &);
231template <
class T, std::
size_t N> tag
swap(T (&a)[N], T (&b)[N]);
235template <
class,
class> std::false_type can_swap(...) noexcept(false);
236template <class T, class U,
237 class = decltype(swap(std::declval<T &>(), std::declval<U &>()))>
238std::true_type can_swap(
int) noexcept(noexcept(swap(std::declval<T &>(),
239 std::declval<U &>())));
241template <class, class> std::false_type uses_std(...);
242template <class T, class U>
243std::is_same<decltype(swap(std::declval<T &>(), std::declval<U &>())), tag>
247struct is_std_swap_noexcept
248 : std::integral_constant<
bool,
249 std::is_nothrow_move_constructible<T>::value &&
250 std::is_nothrow_move_assignable<T>::value> {};
252template <
class T, std::
size_t N>
253struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
255template <
class T,
class U>
256struct is_adl_swap_noexcept
257 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
260template <
class T,
class U = T>
262 : std::integral_constant<
264 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
265 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
266 (std::is_move_assignable<T>::value &&
267 std::is_move_constructible<T>::value))> {};
269template <
class T, std::
size_t N>
271 : std::integral_constant<
273 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
274 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
276 is_swappable<T, T>::value)> {};
278template <
class T,
class U = T>
280 : std::integral_constant<
282 is_swappable<T, U>::value &&
283 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
284 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
285 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
286 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
290template <
class T,
class E>
294template <
class T,
class E,
class U>
296 std::is_constructible<T, U &&>::value &&
297 !std::is_same<std::decay_t<U>, std::in_place_t>
::value &&
298 !std::is_same<expected<T, E>, std::decay_t<U>>
::value &&
299 !std::is_same<unexpected<E>, std::decay_t<U>>
::value>;
301template <
class T,
class E,
class U,
class G,
class UR,
class GR>
303 std::is_constructible<T, UR>::value &&
304 std::is_constructible<E, GR>::value &&
305 !std::is_constructible<T, expected<U, G> &>
::value &&
306 !std::is_constructible<T, expected<U, G> &&>
::value &&
307 !std::is_constructible<T, const expected<U, G> &>
::value &&
308 !std::is_constructible<T, const expected<U, G> &&>
::value &&
309 !std::is_convertible<expected<U, G> &,
T>
::value &&
310 !std::is_convertible<expected<U, G> &&,
T>
::value &&
311 !std::is_convertible<const expected<U, G> &,
T>
::value &&
312 !std::is_convertible<const expected<U, G> &&,
T>
::value>;
314template <
class T,
class U>
315using is_void_or = std::conditional_t<std::is_void<T>::value, std::true_type,
U>;
341 bool = std::is_trivially_destructible<E>::value>
343 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
344 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
346 template <
class... Args,
347 std::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
349 constexpr expected_storage_base(std::in_place_t, Args &&...args)
350 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
352 template <
class U,
class... Args,
353 std::enable_if_t<std::is_constructible<
354 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
355 constexpr expected_storage_base(std::in_place_t, std::initializer_list<U> il,
357 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
358 template <
class... Args,
359 std::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
361 constexpr explicit expected_storage_base(unexpect_t, Args &&...args)
362 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
364 template <
class U,
class... Args,
365 std::enable_if_t<std::is_constructible<
366 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
367 constexpr explicit expected_storage_base(unexpect_t,
368 std::initializer_list<U> il,
370 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
372 ~expected_storage_base() {
376 m_unexpect.~unexpected<E>();
381 unexpected<E> m_unexpect;
393 template <
class...
Args,
394 std::enable_if_t<std::is_constructible<
T,
Args &&...>
::value> * =
399 template <
class U,
class...
Args,
400 std::enable_if_t<std::is_constructible<
401 T, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
405 template <
class...
Args,
406 std::enable_if_t<std::is_constructible<
E,
Args &&...>
::value> * =
411 template <
class U,
class...
Args,
412 std::enable_if_t<std::is_constructible<
413 E, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
415 std::initializer_list<U>
il,
434 template <
class...
Args,
435 std::enable_if_t<std::is_constructible<
T,
Args &&...>
::value> * =
440 template <
class U,
class...
Args,
441 std::enable_if_t<std::is_constructible<
442 T, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
446 template <
class...
Args,
447 std::enable_if_t<std::is_constructible<
E,
Args &&...>
::value> * =
452 template <
class U,
class...
Args,
453 std::enable_if_t<std::is_constructible<
454 E, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
456 std::initializer_list<U>
il,
479 template <
class...
Args,
480 std::enable_if_t<std::is_constructible<
T,
Args &&...>
::value> * =
485 template <
class U,
class...
Args,
486 std::enable_if_t<std::is_constructible<
487 T, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
491 template <
class...
Args,
492 std::enable_if_t<std::is_constructible<
E,
Args &&...>
::value> * =
497 template <
class U,
class...
Args,
498 std::enable_if_t<std::is_constructible<
499 E, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
501 std::initializer_list<U>
il,
531 template <
class...
Args,
532 std::enable_if_t<std::is_constructible<
E,
Args &&...>
::value> * =
537 template <
class U,
class...
Args,
538 std::enable_if_t<std::is_constructible<
539 E, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
541 std::initializer_list<U>
il,
561 template <
class...
Args,
562 std::enable_if_t<std::is_constructible<
E,
Args &&...>
::value> * =
567 template <
class U,
class...
Args,
568 std::enable_if_t<std::is_constructible<
569 E, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
571 std::initializer_list<U>
il,
590template <
class T,
class E>
595 new (std::addressof(this->
m_val))
T(std::forward<Args>(
args)...);
600 new (std::addressof(this->
m_val))
T(std::forward<Rhs>(
rhs).get());
610#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
618 template <
class U =
T,
619 std::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
632 template <
class U =
T,
633 std::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
634 std::is_nothrow_move_constructible<U>::value>
651 template <
class U =
T,
652 std::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
653 !std::is_nothrow_move_constructible<U>::value>
660#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
676 template <
class U =
T,
677 std::enable_if_t<std::is_nothrow_move_constructible<U>::value>
688 template <
class U =
T,
689 std::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
695#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
737 get() = std::forward<Rhs>(
rhs).get();
743 if (!
rhs.m_has_val) {
744 geterr() = std::forward<Rhs>(
rhs).geterr();
751 constexpr T &
get() & {
return this->
m_val; }
753 constexpr T &&
get() && {
return std::move(this->
m_val); }
754 constexpr const T &&
get()
const && {
return std::move(this->
m_val); }
774 using expected_storage_base<void, E>::expected_storage_base;
776 template <
class... Args>
void construct() noexcept { this->m_has_val =
true; }
780 template <
class Rhs>
void construct_with(Rhs &&) noexcept {
781 this->m_has_val =
true;
784 template <
class... Args>
void construct_error(Args &&...args)
noexcept {
785 new (std::addressof(this->m_unexpect))
786 unexpected<E>(std::forward<Args>(args)...);
787 this->m_has_val =
false;
790 template <
class Rhs>
void assign(Rhs &&rhs)
noexcept {
791 if (!this->m_has_val) {
793 geterr().~unexpected<E>();
796 geterr() = std::forward<Rhs>(rhs).geterr();
799 if (!rhs.m_has_val) {
800 construct_error(std::forward<Rhs>(rhs).geterr());
805 bool has_value()
const {
return this->m_has_val; }
807 constexpr unexpected<E> &geterr() & {
808 return this->m_unexpect;
810 constexpr const unexpected<E> &geterr() const & {
return this->m_unexpect; }
811 constexpr unexpected<E> &&geterr() && {
812 return std::move(this->m_unexpect);
814 constexpr const unexpected<E> &&geterr() const && {
815 return std::move(this->m_unexpect);
818 constexpr void destroy_val() {
825template <
class T,
class E,
833template <
class T,
class E>
840 if (
rhs.has_value()) {
853template <
class T,
class E,
855 &&std::is_trivially_move_constructible<E>::value>
857 using expected_copy_base<T, E>::expected_copy_base;
860template <
class T,
class E>
862 using expected_copy_base<T, E>::expected_copy_base;
864 expected_move_base() =
default;
865 expected_move_base(
const expected_move_base &rhs) =
default;
867 expected_move_base(expected_move_base &&rhs)
noexcept(
868 std::is_nothrow_move_constructible<T>::value)
869 : expected_copy_base<T, E>(no_init) {
870 if (rhs.has_value()) {
871 this->construct_with(std::move(rhs));
873 this->construct_error(std::move(rhs.geterr()));
876 expected_move_base &operator=(
const expected_move_base &rhs) =
default;
877 expected_move_base &operator=(expected_move_base &&rhs) =
default;
881template <
class T,
class E,
893template <
class T,
class E>
910template <
class T,
class E,
913 std::is_trivially_move_constructible<T>,
914 std::is_trivially_move_assignable<T>>>
::
915 value &&std::is_trivially_destructible<E>::value
916 &&std::is_trivially_move_constructible<E>::value
917 &&std::is_trivially_move_assignable<E>::value>
919 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
922template <
class T,
class E>
925 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
927 expected_move_assign_base() =
default;
928 expected_move_assign_base(
const expected_move_assign_base &rhs) =
default;
930 expected_move_assign_base(expected_move_assign_base &&rhs) =
default;
932 expected_move_assign_base &
933 operator=(
const expected_move_assign_base &rhs) =
default;
935 expected_move_assign_base &
936 operator=(expected_move_assign_base &&rhs)
noexcept(
937 std::is_nothrow_move_constructible<T>::value
938 &&std::is_nothrow_move_assignable<T>::value) {
939 this->assign(std::move(rhs));
946template <
class T,
class E,
947 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
948 std::is_copy_constructible<E>::value),
949 bool EnableMove = (is_move_constructible_or_void<T>::value &&
950 std::is_move_constructible<E>::value)>
952 expected_delete_ctor_base() =
default;
953 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
954 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
955 expected_delete_ctor_base &
956 operator=(const expected_delete_ctor_base &) = default;
957 expected_delete_ctor_base &
958 operator=(expected_delete_ctor_base &&) noexcept = default;
961template <class T, class E>
962struct expected_delete_ctor_base<T, E, true, false> {
963 expected_delete_ctor_base() =
default;
964 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
965 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
966 expected_delete_ctor_base &
967 operator=(const expected_delete_ctor_base &) = default;
968 expected_delete_ctor_base &
969 operator=(expected_delete_ctor_base &&) noexcept = default;
972template <class T, class E>
973struct expected_delete_ctor_base<T, E, false, true> {
974 expected_delete_ctor_base() =
default;
975 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
976 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
977 expected_delete_ctor_base &
978 operator=(const expected_delete_ctor_base &) = default;
979 expected_delete_ctor_base &
980 operator=(expected_delete_ctor_base &&) noexcept = default;
983template <class T, class E>
984struct expected_delete_ctor_base<T, E, false, false> {
985 expected_delete_ctor_base() =
default;
986 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
987 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
988 expected_delete_ctor_base &
989 operator=(const expected_delete_ctor_base &) = default;
990 expected_delete_ctor_base &
991 operator=(expected_delete_ctor_base &&) noexcept = default;
997template <class T, class E,
998 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
999 std::is_copy_constructible<E>::value &&
1000 is_copy_assignable_or_void<T>::value &&
1001 std::is_copy_assignable<E>::value),
1002 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1003 std::is_move_constructible<E>::value &&
1004 is_move_assignable_or_void<T>::value &&
1005 std::is_move_assignable<E>::value)>
1006struct expected_delete_assign_base {
1007 expected_delete_assign_base() =
default;
1008 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1009 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1011 expected_delete_assign_base &
1012 operator=(const expected_delete_assign_base &) = default;
1013 expected_delete_assign_base &
1014 operator=(expected_delete_assign_base &&) noexcept = default;
1017template <class T, class E>
1018struct expected_delete_assign_base<T, E, true, false> {
1019 expected_delete_assign_base() =
default;
1020 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1021 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1023 expected_delete_assign_base &
1024 operator=(const expected_delete_assign_base &) = default;
1025 expected_delete_assign_base &
1026 operator=(expected_delete_assign_base &&) noexcept = delete;
1029template <class T, class E>
1030struct expected_delete_assign_base<T, E, false, true> {
1031 expected_delete_assign_base() =
default;
1032 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1033 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1035 expected_delete_assign_base &
1036 operator=(const expected_delete_assign_base &) = delete;
1037 expected_delete_assign_base &
1038 operator=(expected_delete_assign_base &&) noexcept = default;
1041template <class T, class E>
1042struct expected_delete_assign_base<T, E, false, false> {
1043 expected_delete_assign_base() =
default;
1044 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1045 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1047 expected_delete_assign_base &
1048 operator=(const expected_delete_assign_base &) = delete;
1049 expected_delete_assign_base &
1050 operator=(expected_delete_assign_base &&) noexcept = delete;
1055struct default_constructor_tag {
1056 explicit constexpr default_constructor_tag() =
default;
1062template <
class T,
class E,
1064 std::is_default_constructible<T>::value || std::is_void<T>::value>
1065struct expected_default_ctor_base {
1066 constexpr expected_default_ctor_base() noexcept = default;
1067 constexpr expected_default_ctor_base(
1068 expected_default_ctor_base const &) noexcept = default;
1069 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1071 expected_default_ctor_base &
1072 operator=(expected_default_ctor_base const &) noexcept = default;
1073 expected_default_ctor_base &
1074 operator=(expected_default_ctor_base &&) noexcept = default;
1076 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1080template <
class T,
class E>
struct expected_default_ctor_base<T, E, false> {
1081 constexpr expected_default_ctor_base() noexcept = delete;
1082 constexpr expected_default_ctor_base(
1083 expected_default_ctor_base const &) noexcept = default;
1084 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1086 expected_default_ctor_base &
1087 operator=(expected_default_ctor_base const &) noexcept = default;
1088 expected_default_ctor_base &
1089 operator=(expected_default_ctor_base &&) noexcept = default;
1091 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1095template <
typename E>
1096class bad_expected_access;
1098template <>
class bad_expected_access<void> :
public std::exception
1101 virtual const char *what() const noexcept
override {
1102 return "Bad expected access";
1106 bad_expected_access() noexcept {}
1107 bad_expected_access(
const bad_expected_access&) =
default;
1108 bad_expected_access(bad_expected_access&&) =
default;
1109 bad_expected_access& operator=(
const bad_expected_access&) =
default;
1110 bad_expected_access& operator=(bad_expected_access&&) =
default;
1111 ~bad_expected_access() =
default;
1115class bad_expected_access :
public bad_expected_access<void>
1118 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1120 const E &error() const & {
return m_val; }
1121 E &error() & {
return m_val; }
1122 const E &&error() const && {
return std::move(m_val); }
1123 E &&error() && {
return std::move(m_val); }
1129template <
class T,
class E>
1130class expected :
private detail::expected_move_assign_base<T, E>,
1131 private detail::expected_delete_ctor_base<T, E>,
1132 private detail::expected_delete_assign_base<T, E>,
1133 private detail::expected_default_ctor_base<T, E> {
1134 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1135 static_assert(!std::is_same<T, std::remove_cv<std::in_place_t>::type>::value,
1136 "T must not be std::in_place_t");
1137 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1138 "T must not be unexpect_t");
1140 !std::is_same<T, typename std::remove_cv<unexpected<E>>::type>::value,
1141 "T must not be unexpected<E>");
1142 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1144 T *valptr() {
return std::addressof(this->m_val); }
1145 const T *valptr()
const {
return std::addressof(this->m_val); }
1146 unexpected<E> *errptr() {
return std::addressof(this->m_unexpect); }
1147 const unexpected<E> *errptr()
const {
1148 return std::addressof(this->m_unexpect);
1151 template <
class U = T,
1152 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1153 constexpr U &val() {
1156 constexpr unexpected<E> &err() {
return this->m_unexpect; }
1158 template <
class U = T,
1159 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1160 constexpr const U &val()
const {
1163 constexpr const unexpected<E> &err()
const {
return this->m_unexpect; }
1165 using impl_base = detail::expected_move_assign_base<T, E>;
1166 using ctor_base = detail::expected_default_ctor_base<T, E>;
1169 typedef T value_type;
1170 typedef E error_type;
1171 typedef unexpected<E> unexpected_type;
1173 template <
class F>
constexpr auto and_then(F &&f) & {
1174 return and_then_impl(*
this, std::forward<F>(f));
1176 template <
class F>
constexpr auto and_then(F &&f) && {
1177 return and_then_impl(std::move(*
this), std::forward<F>(f));
1179 template <
class F>
constexpr auto and_then(F &&f)
const & {
1180 return and_then_impl(*
this, std::forward<F>(f));
1182 template <
class F>
constexpr auto and_then(F &&f)
const && {
1183 return and_then_impl(std::move(*
this), std::forward<F>(f));
1186 template <
class F>
constexpr auto map(F &&f) & {
1187 return expected_map_impl(*
this, std::forward<F>(f));
1189 template <
class F>
constexpr auto map(F &&f) && {
1190 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1192 template <
class F>
constexpr auto map(F &&f)
const & {
1193 return expected_map_impl(*
this, std::forward<F>(f));
1195 template <
class F>
constexpr auto map(F &&f)
const && {
1196 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1199 template <
class F>
constexpr auto transform(F &&f) & {
1200 return expected_map_impl(*
this, std::forward<F>(f));
1202 template <
class F>
constexpr auto transform(F &&f) && {
1203 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1205 template <
class F>
constexpr auto transform(F &&f)
const & {
1206 return expected_map_impl(*
this, std::forward<F>(f));
1208 template <
class F>
constexpr auto transform(F &&f)
const && {
1209 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1212 template <
class F>
constexpr auto map_error(F &&f) & {
1213 return map_error_impl(*
this, std::forward<F>(f));
1215 template <
class F>
constexpr auto map_error(F &&f) && {
1216 return map_error_impl(std::move(*
this), std::forward<F>(f));
1218 template <
class F>
constexpr auto map_error(F &&f)
const & {
1219 return map_error_impl(*
this, std::forward<F>(f));
1221 template <
class F>
constexpr auto map_error(F &&f)
const && {
1222 return map_error_impl(std::move(*
this), std::forward<F>(f));
1225 template <
class F>
constexpr auto transform_error(F &&f) & {
1226 return map_error_impl(*
this, std::forward<F>(f));
1228 template <
class F>
constexpr auto transform_error(F &&f) && {
1229 return map_error_impl(std::move(*
this), std::forward<F>(f));
1231 template <
class F>
constexpr auto transform_error(F &&f)
const & {
1232 return map_error_impl(*
this, std::forward<F>(f));
1234 template <
class F>
constexpr auto transform_error(F &&f)
const && {
1235 return map_error_impl(std::move(*
this), std::forward<F>(f));
1238 template <
class F> expected
constexpr or_else(F &&f) & {
1239 return or_else_impl(*
this, std::forward<F>(f));
1242 template <
class F> expected
constexpr or_else(F &&f) && {
1243 return or_else_impl(std::move(*
this), std::forward<F>(f));
1246 template <
class F> expected
constexpr or_else(F &&f)
const & {
1247 return or_else_impl(*
this, std::forward<F>(f));
1250 template <
class F> expected
constexpr or_else(F &&f)
const && {
1251 return or_else_impl(std::move(*
this), std::forward<F>(f));
1254 constexpr expected() =
default;
1255 constexpr expected(
const expected &rhs) =
default;
1256 constexpr expected(expected &&rhs) =
default;
1257 expected &operator=(
const expected &rhs) =
default;
1258 expected &operator=(expected &&rhs) =
default;
1260 template <
class... Args,
1261 std::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1263 constexpr expected(std::in_place_t, Args &&...args)
1264 : impl_base(std::in_place, std::forward<Args>(args)...),
1265 ctor_base(detail::default_constructor_tag{}) {}
1267 template <
class U,
class... Args,
1268 std::enable_if_t<std::is_constructible<
1269 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1270 constexpr expected(std::in_place_t, std::initializer_list<U> il, Args &&...args)
1271 : impl_base(std::in_place, il, std::forward<Args>(args)...),
1272 ctor_base(detail::default_constructor_tag{}) {}
1274 template <
class G = E,
1275 std::enable_if_t<std::is_constructible<E, const G &>::value> * =
1277 std::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1279 explicit constexpr expected(
const unexpected<G> &e)
1280 : impl_base(unexpect, e.value()),
1281 ctor_base(detail::default_constructor_tag{}) {}
1285 std::enable_if_t<std::is_constructible<E, const G &>::value> * =
1287 std::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1288 constexpr expected(unexpected<G>
const &e)
1289 : impl_base(unexpect, e.value()),
1290 ctor_base(detail::default_constructor_tag{}) {}
1294 std::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1295 std::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1296 explicit constexpr expected(unexpected<G> &&e)
noexcept(
1297 std::is_nothrow_constructible<E, G &&>::value)
1298 : impl_base(unexpect, std::move(e.value())),
1299 ctor_base(detail::default_constructor_tag{}) {}
1303 std::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1304 std::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1305 constexpr expected(unexpected<G> &&e)
noexcept(
1306 std::is_nothrow_constructible<E, G &&>::value)
1307 : impl_base(unexpect, std::move(e.value())),
1308 ctor_base(detail::default_constructor_tag{}) {}
1310 template <
class... Args,
1311 std::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1313 constexpr explicit expected(unexpect_t, Args &&...args)
1314 : impl_base(unexpect, std::forward<Args>(args)...),
1315 ctor_base(detail::default_constructor_tag{}) {}
1317 template <
class U,
class... Args,
1318 std::enable_if_t<std::is_constructible<
1319 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1320 constexpr explicit expected(unexpect_t, std::initializer_list<U> il,
1322 : impl_base(unexpect, il, std::forward<Args>(args)...),
1323 ctor_base(detail::default_constructor_tag{}) {}
1325 template <
class U,
class G,
1326 std::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1327 std::is_convertible<G const &, E>::value)> * =
1329 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1331 explicit constexpr expected(
const expected<U, G> &rhs)
1332 : ctor_base(detail::default_constructor_tag{}) {
1333 if (rhs.has_value()) {
1334 this->construct(*rhs);
1336 this->construct_error(rhs.error());
1340 template <
class U,
class G,
1341 std::enable_if_t<(std::is_convertible<U const &, T>::value &&
1342 std::is_convertible<G const &, E>::value)> * =
1344 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1346 constexpr expected(
const expected<U, G> &rhs)
1347 : ctor_base(detail::default_constructor_tag{}) {
1348 if (
rhs.has_value()) {
1357 std::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1358 std::is_convertible<G &&, E>::value)> * =
nullptr,
1359 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1361 :
ctor_base(detail::default_constructor_tag{}) {
1362 if (
rhs.has_value()) {
1371 std::enable_if_t<(std::is_convertible<U &&, T>::value &&
1372 std::is_convertible<G &&, E>::value)> * =
nullptr,
1373 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1376 if (
rhs.has_value()) {
1385 std::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1386 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1387 explicit constexpr expected(
U &&
v)
1392 std::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1393 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1394 constexpr expected(
U &&
v)
1398 class U =
T,
class G =
T,
1399 std::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1401 std::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1403 (!std::is_same<expected<T, E>, std::decay_t<U>>
::value &&
1404 !std::conjunction<std::is_scalar<T>,
1405 std::is_same<T, std::decay_t<U>>>
::value &&
1406 std::is_constructible<T, U>::value &&
1407 std::is_assignable<G &, U>::value &&
1408 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1409 expected &
operator=(
U &&
v) {
1411 val() = std::forward<U>(
v);
1413 err().~unexpected<
E>();
1435 val() = std::forward<U>(
v);
1437 auto tmp = std::move(
err());
1438 err().~unexpected<
E>();
1440#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
1457 template <
class G =
E,
1458 std::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1459 std::is_assignable<G &, G>::value> * =
nullptr>
1493 err().~unexpected<
E>();
1506 auto tmp = std::move(
err());
1507 err().~unexpected<
E>();
1509#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
1524 template <
class U,
class...
Args,
1525 std::enable_if_t<std::is_nothrow_constructible<
1526 T, std::initializer_list<U> &,
Args &&...>
::value> * =
nullptr>
1527 void emplace(std::initializer_list<U>
il,
Args &&...
args) {
1529 T t(
il, std::forward<Args>(
args)...);
1530 val() = std::move(
t);
1532 err().~unexpected<
E>();
1543 T t(
il, std::forward<Args>(
args)...);
1544 val() = std::move(
t);
1546 auto tmp = std::move(
err());
1547 err().~unexpected<
E>();
1549#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
1582 std::is_nothrow_move_constructible<E>::value) {
1590 rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1591 typename std::is_nothrow_move_constructible<E>::type{});
1610#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
1631 auto temp = std::move(
rhs.err());
1632 rhs.err().~unexpected_type();
1633#ifdef GUL17_EXPECTED_EXCEPTIONS_ENABLED
1652 template <
class OT = T,
class OE = E>
1653 std::enable_if_t<detail::is_swappable<OT>::value &&
1654 detail::is_swappable<OE>::value &&
1655 (std::is_nothrow_move_constructible<OT>::value ||
1656 std::is_nothrow_move_constructible<OE>::value)>
1658 std::is_nothrow_move_constructible<T>::value
1659 &&detail::is_nothrow_swappable<T>::value
1660 &&std::is_nothrow_move_constructible<E>::value
1661 &&detail::is_nothrow_swappable<E>::value) {
1674 constexpr const T *operator->()
const {
1678 constexpr T *operator->() {
1683 template <
class U =
T,
1684 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1685 constexpr const U &operator*()
const & {
1689 template <
class U =
T,
1690 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1691 constexpr U &operator*() & {
1695 template <
class U =
T,
1696 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1697 constexpr const U &&operator*()
const && {
1699 return std::move(
val());
1701 template <
class U =
T,
1702 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1703 constexpr U &&operator*() && {
1705 return std::move(
val());
1711 template <
class U =
T,
1712 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1718 template <
class U =
T,
1719 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1725 template <
class U =
T,
1726 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1730 return std::move(
val());
1732 template <
class U =
T,
1733 std::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1734 constexpr U &&
value() && {
1737 return std::move(
val());
1742 return err().value();
1746 return err().value();
1752 constexpr E &&
error() && {
1757 template <
class U>
constexpr T value_or(
U &&
v)
const & {
1758 static_assert(std::is_copy_constructible<T>::value &&
1759 std::is_convertible<U &&, T>::value,
1760 "T must be copy-constructible and convertible to from U&&");
1761 return bool(*
this) ? **
this :
static_cast<T>(std::forward<U>(
v));
1763 template <
class U>
constexpr T value_or(
U &&
v) && {
1764 static_assert(std::is_move_constructible<T>::value &&
1765 std::is_convertible<U &&, T>::value,
1766 "T must be move-constructible and convertible to from U&&");
1772template <
class Exp>
using exp_t =
typename std::decay_t<Exp>::value_type;
1773template <
class Exp>
using err_t =
typename std::decay_t<Exp>::error_type;
1776template <
class Exp,
class F,
1777 std::enable_if_t<!std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1778 class Ret =
decltype(
invoke(std::declval<F>(),
1779 *std::declval<Exp>()))>
1781 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1783 return exp.has_value()
1784 ?
invoke(std::forward<F>(
f), *std::forward<Exp>(
exp))
1788template <
class Exp,
class F,
1789 std::enable_if_t<std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1790 class Ret =
decltype(
invoke(std::declval<F>()))>
1792 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1794 return exp.has_value() ?
invoke(std::forward<F>(
f))
1798template <
class Exp,
class F,
1799 std::enable_if_t<!std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1800 class Ret =
decltype(
invoke(std::declval<F>(),
1801 *std::declval<Exp>())),
1802 std::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1806 *std::forward<Exp>(
exp)))
1810template <
class Exp,
class F,
1811 std::enable_if_t<!std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1812 class Ret =
decltype(
invoke(std::declval<F>(),
1813 *std::declval<Exp>())),
1814 std::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1817 if (
exp.has_value()) {
1818 invoke(std::forward<F>(
f), *std::forward<Exp>(
exp));
1825template <
class Exp,
class F,
1826 std::enable_if_t<std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1827 class Ret =
decltype(
invoke(std::declval<F>())),
1828 std::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1835template <
class Exp,
class F,
1836 std::enable_if_t<std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1837 class Ret =
decltype(
invoke(std::declval<F>())),
1838 std::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1841 if (
exp.has_value()) {
1849template <
class Exp,
class F,
1850 std::enable_if_t<!std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1851 class Ret =
decltype(
invoke(std::declval<F>(),
1852 std::declval<Exp>().
error())),
1853 std::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1856 return exp.has_value()
1861template <
class Exp,
class F,
1862 std::enable_if_t<!std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1863 class Ret =
decltype(
invoke(std::declval<F>(),
1864 std::declval<Exp>().
error())),
1865 std::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1868 if (
exp.has_value()) {
1875template <
class Exp,
class F,
1876 std::enable_if_t<std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1877 class Ret =
decltype(
invoke(std::declval<F>(),
1878 std::declval<Exp>().
error())),
1879 std::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1882 return exp.has_value()
1887template <
class Exp,
class F,
1888 std::enable_if_t<std::is_void<exp_t<Exp>>
::value> * =
nullptr,
1889 class Ret =
decltype(
invoke(std::declval<F>(),
1890 std::declval<Exp>().
error())),
1891 std::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1894 if (
exp.has_value()) {
1902template <
class Exp,
class F,
1903 class Ret =
decltype(
invoke(std::declval<F>(),
1904 std::declval<Exp>().
error())),
1905 std::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1907 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1908 return exp.has_value() ? std::forward<Exp>(
exp)
1912template <
class Exp,
class F,
1913 class Ret =
decltype(
invoke(std::declval<F>(),
1914 std::declval<Exp>().
error())),
1915 std::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1917 return exp.has_value() ? std::forward<Exp>(
exp)
1924template <
class T,
class E,
class U,
class F>
1927 return (
lhs.has_value() !=
rhs.has_value())
1931template <
class T,
class E,
class U,
class F>
1934 return (
lhs.has_value() !=
rhs.has_value())
1938template <
class E,
class F>
1941 return (
lhs.has_value() !=
rhs.has_value())
1943 : (!
lhs.has_value() ?
lhs.error() ==
rhs.error() :
true);
1945template <
class E,
class F>
1948 return (
lhs.has_value() !=
rhs.has_value())
1950 : (!
lhs.has_value() ?
lhs.error() ==
rhs.error() :
false);
1953template <
class T,
class E,
class U>
1955 return x.has_value() ? *
x ==
v :
false;
1957template <
class T,
class E,
class U>
1959 return x.has_value() ? *
x ==
v :
false;
1961template <
class T,
class E,
class U>
1963 return x.has_value() ? *
x !=
v :
true;
1965template <
class T,
class E,
class U>
1967 return x.has_value() ? *
x !=
v :
true;
1970template <
class T,
class E>
1972 return x.has_value() ?
false :
x.error() ==
e.value();
1974template <
class T,
class E>
1976 return x.has_value() ?
false :
x.error() ==
e.value();
1978template <
class T,
class E>
1980 return x.has_value() ?
true :
x.error() !=
e.value();
1982template <
class T,
class E>
1984 return x.has_value() ?
true :
x.error() !=
e.value();
1987template <
class T,
class E,
1988 std::enable_if_t<(std::is_void<T>::value ||
1989 std::is_move_constructible<T>::value) &&
1990 detail::is_swappable<T>::value &&
1991 std::is_move_constructible<E>::value &&
1992 detail::is_swappable<E>::value> * =
nullptr>
The exception thrown by gul17::expected if value() is called, but no value is present.
Definition expected.h:55
An expected<T, E> is an object that normally contains an "expected" object of type T,...
Definition expected.h:93
Class template for constructing the unexpected value of an expected object.
Definition expected.h:101
void swap(SmallVector< ElementT, in_capacity > &a, SmallVector< ElementT, in_capacity > &b)
Exchange the contents of one SmallVector with those of another one.
Definition SmallVector.h:1656
auto constexpr bit_set(unsigned bit) noexcept -> ReturnT
Set a bit in an integral type.
Definition bit_manip.h:121
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition span.h:537
Namespace gul17 contains all functions and classes of the General Utility Library.
Definition doxygen.h:26
Some metaprogramming traits for the General Utility Library.