25 #ifndef GUL14_EXPECTED_H_
26 #define GUL14_EXPECTED_H_
31 #include <type_traits>
86 template <
typename T,
typename E>
99 #if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
100 #define GUL14_EXPECTED_EXCEPTIONS_ENABLED
103 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
104 #define GUL14_EXPECTED_GCC54
107 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
108 #define GUL14_EXPECTED_GCC55
111 #if (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
112 #ifndef GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
113 #define GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
116 struct is_trivially_copy_constructible
117 : std::is_trivially_copy_constructible<T> {};
118 #ifdef _GLIBCXX_VECTOR
119 template <
class T,
class A>
120 struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
125 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
126 gul14::detail::is_trivially_copy_constructible<T>
127 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
128 std::is_trivially_copy_assignable<T>
129 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
130 std::is_trivially_destructible<T>
132 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
133 std::is_trivially_copy_constructible<T>
134 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
135 std::is_trivially_copy_assignable<T>
136 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
137 std::is_trivially_destructible<T>
140 template <
class T,
class E>
class expected;
146 static_assert(!std::is_same<E, void>::value,
"E must not be void");
148 unexpected() =
delete;
149 constexpr
explicit unexpected(
const E &e) : m_val(e) {}
151 constexpr
explicit unexpected(E &&e) : m_val(std::move(e)) {}
153 template <
class... Args,
typename std::enable_if<std::is_constructible<
154 E, Args &&...>::value>::type * =
nullptr>
155 constexpr
explicit unexpected(Args &&...args)
156 : m_val(std::forward<Args>(args)...) {}
158 class U,
class... Args,
159 typename std::enable_if<std::is_constructible<
160 E, std::initializer_list<U> &, Args &&...>::value>::type * =
nullptr>
161 constexpr
explicit unexpected(std::initializer_list<U> l, Args &&...args)
162 : m_val(l, std::forward<Args>(args)...) {}
164 constexpr
const E &value() const & {
return m_val; }
165 constexpr E &value() & {
return m_val; }
166 constexpr E &&value() && {
return std::move(m_val); }
167 constexpr
const E &&value() const && {
return std::move(m_val); }
173 #ifdef __cpp_deduction_guides
174 template <
class E> unexpected(E) -> unexpected<E>;
178 constexpr
bool operator==(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
179 return lhs.value() == rhs.value();
182 constexpr
bool operator!=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
183 return lhs.value() != rhs.value();
186 constexpr
bool operator<(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
187 return lhs.value() < rhs.value();
190 constexpr
bool operator<=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
191 return lhs.value() <= rhs.value();
194 constexpr
bool operator>(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
195 return lhs.value() > rhs.value();
198 constexpr
bool operator>=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
199 return lhs.value() >= rhs.value();
203 unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
204 return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
208 unexpect_t() =
default;
210 static constexpr unexpect_t unexpect{};
213 template <
typename E>
214 [[noreturn]] constexpr
void throw_exception(E &&e) {
215 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
216 throw std::forward<E>(e);
222 __builtin_unreachable();
227 #ifndef GUL14_TRAITS_MUTEX
228 #define GUL14_TRAITS_MUTEX
230 template <
class T>
using remove_const_t =
typename std::remove_const<T>::type;
232 using remove_reference_t =
typename std::remove_reference<T>::type;
233 template <
class T>
using decay_t =
typename std::decay<T>::type;
234 template <
bool E,
class T =
void>
235 using enable_if_t =
typename std::enable_if<E, T>::type;
236 template <
bool B,
class T,
class F>
237 using conditional_t =
typename std::conditional<B, T, F>::type;
240 template <
class...>
struct conjunction : std::true_type {};
241 template <
class B>
struct conjunction<B> : B {};
242 template <
class B,
class... Bs>
243 struct conjunction<B, Bs...>
244 : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
249 typename Fn,
typename... Args,
250 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
int = 0>
251 constexpr
auto invoke(Fn &&f, Args &&...args) noexcept(
252 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
253 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
254 return std::mem_fn(f)(std::forward<Args>(args)...);
257 template <
typename Fn,
typename... Args,
258 typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
259 constexpr
auto invoke(Fn &&f, Args &&...args) noexcept(
260 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
261 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
262 return std::forward<Fn>(f)(std::forward<Args>(args)...);
266 template <
class F,
class,
class... Us>
struct invoke_result_impl;
268 template <
class F,
class... Us>
269 struct invoke_result_impl<
271 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
274 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
277 template <
class F,
class... Us>
278 using invoke_result = invoke_result_impl<F, void, Us...>;
280 template <
class F,
class... Us>
281 using invoke_result_t =
typename invoke_result<F, Us...>::type;
284 namespace swap_adl_tests {
288 template <
class T> tag
swap(T &, T &);
289 template <
class T, std::
size_t N> tag
swap(T (&a)[N], T (&b)[N]);
293 template <
class,
class> std::false_type can_swap(...) noexcept(false);
294 template <class T, class U,
295 class = decltype(
swap(std::declval<T &>(), std::declval<U &>()))>
296 std::true_type can_swap(
int) noexcept(noexcept(
swap(std::declval<T &>(),
297 std::declval<U &>())));
299 template <class, class> std::false_type uses_std(...);
300 template <class T, class U>
301 std::is_same<decltype(
swap(std::declval<T &>(), std::declval<U &>())), tag>
305 struct is_std_swap_noexcept
306 : std::integral_constant<
bool,
307 std::is_nothrow_move_constructible<T>::value &&
308 std::is_nothrow_move_assignable<T>::value> {};
310 template <
class T, std::
size_t N>
311 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
313 template <
class T,
class U>
314 struct is_adl_swap_noexcept
315 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
318 template <
class T,
class U = T>
320 : std::integral_constant<
322 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
323 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
324 (std::is_move_assignable<T>::value &&
325 std::is_move_constructible<T>::value))> {};
327 template <
class T, std::
size_t N>
328 struct is_swappable<T[N], T[N]>
329 : std::integral_constant<
331 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
332 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
334 is_swappable<T, T>::value)> {};
336 template <
class T,
class U = T>
337 struct is_nothrow_swappable
338 : std::integral_constant<
340 is_swappable<T, U>::value &&
341 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
342 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
343 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
344 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
348 template <
class T>
struct is_expected_impl : std::false_type {};
349 template <
class T,
class E>
350 struct is_expected_impl<expected<T, E>> : std::true_type {};
351 template <
class T>
using is_expected = is_expected_impl<decay_t<T>>;
353 template <
class T,
class E,
class U>
354 using expected_enable_forward_value = detail::enable_if_t<
355 std::is_constructible<T, U &&>::value &&
356 !std::is_same<detail::decay_t<U>, in_place_t>::value &&
357 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
358 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
360 template <
class T,
class E,
class U,
class G,
class UR,
class GR>
361 using expected_enable_from_other = detail::enable_if_t<
362 std::is_constructible<T, UR>::value &&
363 std::is_constructible<E, GR>::value &&
364 !std::is_constructible<T, expected<U, G> &>::value &&
365 !std::is_constructible<T, expected<U, G> &&>::value &&
366 !std::is_constructible<T, const expected<U, G> &>::value &&
367 !std::is_constructible<T, const expected<U, G> &&>::value &&
368 !std::is_convertible<expected<U, G> &, T>::value &&
369 !std::is_convertible<expected<U, G> &&, T>::value &&
370 !std::is_convertible<const expected<U, G> &, T>::value &&
371 !std::is_convertible<const expected<U, G> &&, T>::value>;
373 template <
class T,
class U>
374 using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
377 using is_copy_constructible_or_void =
378 is_void_or<T, std::is_copy_constructible<T>>;
381 using is_move_constructible_or_void =
382 is_void_or<T, std::is_move_constructible<T>>;
385 using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
388 using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
391 static constexpr no_init_t no_init{};
399 template <class T, class E, bool = std::is_trivially_destructible<T>::value,
400 bool = std::is_trivially_destructible<E>::value>
401 struct expected_storage_base {
402 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
403 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
405 template <
class... Args,
406 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
408 constexpr expected_storage_base(in_place_t, Args &&...args)
409 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
411 template <
class U,
class... Args,
412 detail::enable_if_t<std::is_constructible<
413 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
414 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
416 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
417 template <
class... Args,
418 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
420 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
421 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
423 template <
class U,
class... Args,
424 detail::enable_if_t<std::is_constructible<
425 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
426 constexpr
explicit expected_storage_base(unexpect_t,
427 std::initializer_list<U> il,
429 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
431 ~expected_storage_base() {
435 m_unexpect.~unexpected<E>();
440 unexpected<E> m_unexpect;
448 template <
class T,
class E>
struct expected_storage_base<T, E, true, true> {
449 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
450 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
452 template <
class... Args,
453 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
455 constexpr expected_storage_base(in_place_t, Args &&...args)
456 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
458 template <
class U,
class... Args,
459 detail::enable_if_t<std::is_constructible<
460 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
461 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
463 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
464 template <
class... Args,
465 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
467 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
468 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
470 template <
class U,
class... Args,
471 detail::enable_if_t<std::is_constructible<
472 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
473 constexpr
explicit expected_storage_base(unexpect_t,
474 std::initializer_list<U> il,
476 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
478 ~expected_storage_base() =
default;
481 unexpected<E> m_unexpect;
488 template <
class T,
class E>
struct expected_storage_base<T, E, true, false> {
489 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
490 constexpr expected_storage_base(no_init_t)
491 : m_no_init(), m_has_val(false) {}
493 template <
class... Args,
494 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
496 constexpr expected_storage_base(in_place_t, Args &&...args)
497 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
499 template <
class U,
class... Args,
500 detail::enable_if_t<std::is_constructible<
501 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
502 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
504 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
505 template <
class... Args,
506 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
508 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
509 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
511 template <
class U,
class... Args,
512 detail::enable_if_t<std::is_constructible<
513 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
514 constexpr
explicit expected_storage_base(unexpect_t,
515 std::initializer_list<U> il,
517 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
519 ~expected_storage_base() {
521 m_unexpect.~unexpected<E>();
527 unexpected<E> m_unexpect;
534 template <
class T,
class E>
struct expected_storage_base<T, E, false, true> {
535 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
536 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
538 template <
class... Args,
539 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
541 constexpr expected_storage_base(in_place_t, Args &&...args)
542 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
544 template <
class U,
class... Args,
545 detail::enable_if_t<std::is_constructible<
546 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
547 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
549 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
550 template <
class... Args,
551 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
553 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
554 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
556 template <
class U,
class... Args,
557 detail::enable_if_t<std::is_constructible<
558 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
559 constexpr
explicit expected_storage_base(unexpect_t,
560 std::initializer_list<U> il,
562 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
564 ~expected_storage_base() {
571 unexpected<E> m_unexpect;
578 template <
class E>
struct expected_storage_base<void, E, false, true> {
584 expected_storage_base() : m_has_val(true) {}
586 constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
588 constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
590 template <
class... Args,
591 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
593 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
594 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
596 template <
class U,
class... Args,
597 detail::enable_if_t<std::is_constructible<
598 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
599 constexpr
explicit expected_storage_base(unexpect_t,
600 std::initializer_list<U> il,
602 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
604 ~expected_storage_base() =
default;
607 unexpected<E> m_unexpect;
614 template <
class E>
struct expected_storage_base<void, E, false, false> {
615 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
616 constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
618 constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
620 template <
class... Args,
621 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
623 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
624 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
626 template <
class U,
class... Args,
627 detail::enable_if_t<std::is_constructible<
628 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
629 constexpr
explicit expected_storage_base(unexpect_t,
630 std::initializer_list<U> il,
632 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
634 ~expected_storage_base() {
636 m_unexpect.~unexpected<E>();
641 unexpected<E> m_unexpect;
649 template <
class T,
class E>
650 struct expected_operations_base : expected_storage_base<T, E> {
651 using expected_storage_base<T, E>::expected_storage_base;
653 template <
class... Args>
void construct(Args &&...args) noexcept {
654 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
655 this->m_has_val =
true;
658 template <
class Rhs>
void construct_with(Rhs &&rhs) noexcept {
659 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
660 this->m_has_val =
true;
663 template <
class... Args>
void construct_error(Args &&...args) noexcept {
664 new (std::addressof(this->m_unexpect))
665 unexpected<E>(std::forward<Args>(args)...);
666 this->m_has_val =
false;
669 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
677 template <
class U = T,
678 detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
680 void assign(
const expected_operations_base &rhs) noexcept {
681 if (!this->m_has_val && rhs.m_has_val) {
682 geterr().~unexpected<E>();
683 construct(rhs.get());
691 template <
class U = T,
692 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
693 std::is_nothrow_move_constructible<U>::value>
695 void assign(
const expected_operations_base &rhs) noexcept {
696 if (!this->m_has_val && rhs.m_has_val) {
698 geterr().~unexpected<E>();
699 construct(std::move(tmp));
710 template <
class U = T,
711 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
712 !std::is_nothrow_move_constructible<U>::value>
714 void assign(
const expected_operations_base &rhs) {
715 if (!this->m_has_val && rhs.m_has_val) {
716 auto tmp = std::move(geterr());
717 geterr().~unexpected<E>();
719 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
721 construct(rhs.get());
723 geterr() = std::move(tmp);
727 construct(rhs.get());
735 template <
class U = T,
736 detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
738 void assign(expected_operations_base &&rhs) noexcept {
739 if (!this->m_has_val && rhs.m_has_val) {
740 geterr().~unexpected<E>();
741 construct(std::move(rhs).
get());
743 assign_common(std::move(rhs));
747 template <
class U = T,
748 detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
750 void assign(expected_operations_base &&rhs) {
751 if (!this->m_has_val && rhs.m_has_val) {
752 auto tmp = std::move(geterr());
753 geterr().~unexpected<E>();
754 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
756 construct(std::move(rhs).
get());
758 geterr() = std::move(tmp);
762 construct(std::move(rhs).
get());
765 assign_common(std::move(rhs));
772 void assign(
const expected_operations_base &rhs) noexcept {
773 if (!this->m_has_val && rhs.m_has_val) {
774 geterr().~unexpected<E>();
775 construct(rhs.get());
781 void assign(expected_operations_base &&rhs) noexcept {
782 if (!this->m_has_val && rhs.m_has_val) {
783 geterr().~unexpected<E>();
784 construct(std::move(rhs).
get());
786 assign_common(std::move(rhs));
793 template <
class Rhs>
void assign_common(Rhs &&rhs) {
794 if (this->m_has_val) {
796 get() = std::forward<Rhs>(rhs).get();
799 construct_error(std::forward<Rhs>(rhs).geterr());
802 if (!rhs.m_has_val) {
803 geterr() = std::forward<Rhs>(rhs).geterr();
808 bool has_value()
const {
return this->m_has_val; }
810 constexpr T &
get() & {
return this->m_val; }
811 constexpr
const T &
get() const & {
return this->m_val; }
812 constexpr T &&
get() && {
return std::move(this->m_val); }
813 constexpr
const T &&
get() const && {
return std::move(this->m_val); }
815 constexpr unexpected<E> &geterr() & {
816 return this->m_unexpect;
818 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
819 constexpr unexpected<E> &&geterr() && {
820 return std::move(this->m_unexpect);
822 constexpr
const unexpected<E> &&geterr() const && {
823 return std::move(this->m_unexpect);
826 constexpr
void destroy_val() {
get().~T(); }
832 struct expected_operations_base<void, E> : expected_storage_base<void, E> {
833 using expected_storage_base<void, E>::expected_storage_base;
835 template <
class... Args>
void construct() noexcept { this->m_has_val =
true; }
839 template <
class Rhs>
void construct_with(Rhs &&) noexcept {
840 this->m_has_val =
true;
843 template <
class... Args>
void construct_error(Args &&...args) noexcept {
844 new (std::addressof(this->m_unexpect))
845 unexpected<E>(std::forward<Args>(args)...);
846 this->m_has_val =
false;
849 template <
class Rhs>
void assign(Rhs &&rhs) noexcept {
850 if (!this->m_has_val) {
852 geterr().~unexpected<E>();
855 geterr() = std::forward<Rhs>(rhs).geterr();
858 if (!rhs.m_has_val) {
859 construct_error(std::forward<Rhs>(rhs).geterr());
864 bool has_value()
const {
return this->m_has_val; }
866 constexpr unexpected<E> &geterr() & {
867 return this->m_unexpect;
869 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
870 constexpr unexpected<E> &&geterr() && {
871 return std::move(this->m_unexpect);
873 constexpr
const unexpected<E> &&geterr() const && {
874 return std::move(this->m_unexpect);
877 constexpr
void destroy_val() {
884 template <
class T,
class E,
885 bool = is_void_or<T, GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
886 value &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
887 struct expected_copy_base : expected_operations_base<T, E> {
888 using expected_operations_base<T, E>::expected_operations_base;
892 template <
class T,
class E>
893 struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
894 using expected_operations_base<T, E>::expected_operations_base;
896 expected_copy_base() =
default;
897 expected_copy_base(
const expected_copy_base &rhs)
898 : expected_operations_base<T, E>(no_init) {
899 if (rhs.has_value()) {
900 this->construct_with(rhs);
902 this->construct_error(rhs.geterr());
906 expected_copy_base(expected_copy_base &&rhs) =
default;
907 expected_copy_base &operator=(
const expected_copy_base &rhs) =
default;
908 expected_copy_base &operator=(expected_copy_base &&rhs) =
default;
912 template <
class T,
class E,
913 bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
914 &&std::is_trivially_move_constructible<E>::value>
915 struct expected_move_base : expected_copy_base<T, E> {
916 using expected_copy_base<T, E>::expected_copy_base;
919 template <
class T,
class E>
920 struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
921 using expected_copy_base<T, E>::expected_copy_base;
923 expected_move_base() =
default;
924 expected_move_base(
const expected_move_base &rhs) =
default;
926 expected_move_base(expected_move_base &&rhs) noexcept(
927 std::is_nothrow_move_constructible<T>::value)
928 : expected_copy_base<T, E>(no_init) {
929 if (rhs.has_value()) {
930 this->construct_with(std::move(rhs));
932 this->construct_error(std::move(rhs.geterr()));
935 expected_move_base &operator=(
const expected_move_base &rhs) =
default;
936 expected_move_base &operator=(expected_move_base &&rhs) =
default;
940 template <
class T,
class E,
942 T, conjunction<GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
943 GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
944 GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
945 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
946 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
947 &&GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
948 struct expected_copy_assign_base : expected_move_base<T, E> {
949 using expected_move_base<T, E>::expected_move_base;
952 template <
class T,
class E>
953 struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
954 using expected_move_base<T, E>::expected_move_base;
956 expected_copy_assign_base() =
default;
957 expected_copy_assign_base(
const expected_copy_assign_base &rhs) =
default;
959 expected_copy_assign_base(expected_copy_assign_base &&rhs) =
default;
960 expected_copy_assign_base &operator=(
const expected_copy_assign_base &rhs) {
964 expected_copy_assign_base &
965 operator=(expected_copy_assign_base &&rhs) =
default;
969 template <
class T,
class E,
971 is_void_or<T, conjunction<std::is_trivially_destructible<T>,
972 std::is_trivially_move_constructible<T>,
973 std::is_trivially_move_assignable<T>>>::
974 value &&std::is_trivially_destructible<E>::value
975 &&std::is_trivially_move_constructible<E>::value
976 &&std::is_trivially_move_assignable<E>::value>
977 struct expected_move_assign_base : expected_copy_assign_base<T, E> {
978 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
981 template <
class T,
class E>
982 struct expected_move_assign_base<T, E, false>
983 : expected_copy_assign_base<T, E> {
984 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
986 expected_move_assign_base() =
default;
987 expected_move_assign_base(
const expected_move_assign_base &rhs) =
default;
989 expected_move_assign_base(expected_move_assign_base &&rhs) =
default;
991 expected_move_assign_base &
992 operator=(
const expected_move_assign_base &rhs) =
default;
994 expected_move_assign_base &
995 operator=(expected_move_assign_base &&rhs) noexcept(
996 std::is_nothrow_move_constructible<T>::value
997 &&std::is_nothrow_move_assignable<T>::value) {
998 this->assign(std::move(rhs));
1005 template <
class T,
class E,
1006 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1007 std::is_copy_constructible<E>::value),
1008 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1009 std::is_move_constructible<E>::value)>
1010 struct expected_delete_ctor_base {
1011 expected_delete_ctor_base() =
default;
1012 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
1013 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1014 expected_delete_ctor_base &
1015 operator=(const expected_delete_ctor_base &) = default;
1016 expected_delete_ctor_base &
1017 operator=(expected_delete_ctor_base &&) noexcept = default;
1020 template <class T, class E>
1021 struct expected_delete_ctor_base<T, E, true, false> {
1022 expected_delete_ctor_base() =
default;
1023 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
1024 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1025 expected_delete_ctor_base &
1026 operator=(const expected_delete_ctor_base &) = default;
1027 expected_delete_ctor_base &
1028 operator=(expected_delete_ctor_base &&) noexcept = default;
1031 template <class T, class E>
1032 struct expected_delete_ctor_base<T, E, false, true> {
1033 expected_delete_ctor_base() =
default;
1034 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1035 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1036 expected_delete_ctor_base &
1037 operator=(const expected_delete_ctor_base &) = default;
1038 expected_delete_ctor_base &
1039 operator=(expected_delete_ctor_base &&) noexcept = default;
1042 template <class T, class E>
1043 struct expected_delete_ctor_base<T, E, false, false> {
1044 expected_delete_ctor_base() =
default;
1045 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1046 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1047 expected_delete_ctor_base &
1048 operator=(const expected_delete_ctor_base &) = default;
1049 expected_delete_ctor_base &
1050 operator=(expected_delete_ctor_base &&) noexcept = default;
1056 template <class T, class E,
1057 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1058 std::is_copy_constructible<E>::value &&
1059 is_copy_assignable_or_void<T>::value &&
1060 std::is_copy_assignable<E>::value),
1061 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1062 std::is_move_constructible<E>::value &&
1063 is_move_assignable_or_void<T>::value &&
1064 std::is_move_assignable<E>::value)>
1065 struct expected_delete_assign_base {
1066 expected_delete_assign_base() =
default;
1067 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1068 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1070 expected_delete_assign_base &
1071 operator=(const expected_delete_assign_base &) = default;
1072 expected_delete_assign_base &
1073 operator=(expected_delete_assign_base &&) noexcept = default;
1076 template <class T, class E>
1077 struct expected_delete_assign_base<T, E, true, false> {
1078 expected_delete_assign_base() =
default;
1079 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1080 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1082 expected_delete_assign_base &
1083 operator=(const expected_delete_assign_base &) = default;
1084 expected_delete_assign_base &
1085 operator=(expected_delete_assign_base &&) noexcept = delete;
1088 template <class T, class E>
1089 struct expected_delete_assign_base<T, E, false, true> {
1090 expected_delete_assign_base() =
default;
1091 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1092 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1094 expected_delete_assign_base &
1095 operator=(const expected_delete_assign_base &) = delete;
1096 expected_delete_assign_base &
1097 operator=(expected_delete_assign_base &&) noexcept = default;
1100 template <class T, class E>
1101 struct expected_delete_assign_base<T, E, false, false> {
1102 expected_delete_assign_base() =
default;
1103 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1104 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1106 expected_delete_assign_base &
1107 operator=(const expected_delete_assign_base &) = delete;
1108 expected_delete_assign_base &
1109 operator=(expected_delete_assign_base &&) noexcept = delete;
1114 struct default_constructor_tag {
1115 explicit constexpr default_constructor_tag() =
default;
1121 template <
class T,
class E,
1123 std::is_default_constructible<T>::value || std::is_void<T>::value>
1124 struct expected_default_ctor_base {
1125 constexpr expected_default_ctor_base() noexcept = default;
1126 constexpr expected_default_ctor_base(
1127 expected_default_ctor_base const &) noexcept = default;
1128 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1130 expected_default_ctor_base &
1131 operator=(expected_default_ctor_base const &) noexcept = default;
1132 expected_default_ctor_base &
1133 operator=(expected_default_ctor_base &&) noexcept = default;
1135 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1139 template <
class T,
class E>
struct expected_default_ctor_base<T, E, false> {
1140 constexpr expected_default_ctor_base() noexcept = delete;
1141 constexpr expected_default_ctor_base(
1142 expected_default_ctor_base const &) noexcept = default;
1143 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1145 expected_default_ctor_base &
1146 operator=(expected_default_ctor_base const &) noexcept = default;
1147 expected_default_ctor_base &
1148 operator=(expected_default_ctor_base &&) noexcept = default;
1150 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1154 template <
typename E>
1155 class bad_expected_access;
1157 template <>
class bad_expected_access<void> :
public std::exception
1160 virtual const char *what() const noexcept
override {
1161 return "Bad expected access";
1165 bad_expected_access() noexcept {}
1166 bad_expected_access(
const bad_expected_access&) =
default;
1167 bad_expected_access(bad_expected_access&&) =
default;
1168 bad_expected_access& operator=(
const bad_expected_access&) =
default;
1169 bad_expected_access& operator=(bad_expected_access&&) =
default;
1170 ~bad_expected_access() =
default;
1174 class bad_expected_access :
public bad_expected_access<void>
1177 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1179 const E &error() const & {
return m_val; }
1180 E &error() & {
return m_val; }
1181 const E &&error() const && {
return std::move(m_val); }
1182 E &&error() && {
return std::move(m_val); }
1188 template <
class T,
class E>
1189 class expected :
private detail::expected_move_assign_base<T, E>,
1190 private detail::expected_delete_ctor_base<T, E>,
1191 private detail::expected_delete_assign_base<T, E>,
1192 private detail::expected_default_ctor_base<T, E> {
1193 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1194 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1195 "T must not be in_place_t");
1196 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1197 "T must not be unexpect_t");
1199 !std::is_same<T,
typename std::remove_cv<unexpected<E>>::type>::value,
1200 "T must not be unexpected<E>");
1201 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1203 T *valptr() {
return std::addressof(this->m_val); }
1204 const T *valptr()
const {
return std::addressof(this->m_val); }
1205 unexpected<E> *errptr() {
return std::addressof(this->m_unexpect); }
1206 const unexpected<E> *errptr()
const {
1207 return std::addressof(this->m_unexpect);
1210 template <
class U = T,
1211 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1212 constexpr U &val() {
1215 constexpr unexpected<E> &err() {
return this->m_unexpect; }
1217 template <
class U = T,
1218 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1219 constexpr
const U &val()
const {
1222 constexpr
const unexpected<E> &err()
const {
return this->m_unexpect; }
1224 using impl_base = detail::expected_move_assign_base<T, E>;
1225 using ctor_base = detail::expected_default_ctor_base<T, E>;
1228 typedef T value_type;
1229 typedef E error_type;
1230 typedef unexpected<E> unexpected_type;
1232 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1234 template <
class F> constexpr
auto and_then(F &&f) & {
1235 return and_then_impl(*
this, std::forward<F>(f));
1237 template <
class F> constexpr
auto and_then(F &&f) && {
1238 return and_then_impl(std::move(*
this), std::forward<F>(f));
1240 template <
class F> constexpr
auto and_then(F &&f)
const & {
1241 return and_then_impl(*
this, std::forward<F>(f));
1243 template <
class F> constexpr
auto and_then(F &&f)
const && {
1244 return and_then_impl(std::move(*
this), std::forward<F>(f));
1251 and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1252 std::forward<F>(f))) {
1253 return and_then_impl(*
this, std::forward<F>(f));
1257 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1258 std::forward<F>(f))) {
1259 return and_then_impl(std::move(*
this), std::forward<F>(f));
1262 constexpr
auto and_then(F &&f)
const & -> decltype(and_then_impl(
1263 std::declval<expected const &>(), std::forward<F>(f))) {
1264 return and_then_impl(*
this, std::forward<F>(f));
1267 constexpr
auto and_then(F &&f)
const && -> decltype(and_then_impl(
1268 std::declval<expected const &&>(), std::forward<F>(f))) {
1269 return and_then_impl(std::move(*
this), std::forward<F>(f));
1274 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1275 template <
class F> constexpr
auto map(F &&f) & {
1276 return expected_map_impl(*
this, std::forward<F>(f));
1278 template <
class F> constexpr
auto map(F &&f) && {
1279 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1281 template <
class F> constexpr
auto map(F &&f)
const & {
1282 return expected_map_impl(*
this, std::forward<F>(f));
1284 template <
class F> constexpr
auto map(F &&f)
const && {
1285 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1289 constexpr decltype(expected_map_impl(
1290 std::declval<expected &>(), std::declval<F &&>()))
1292 return expected_map_impl(*
this, std::forward<F>(f));
1295 constexpr decltype(expected_map_impl(std::declval<expected>(),
1296 std::declval<F &&>()))
1298 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1301 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1302 std::declval<F &&>()))
1303 map(F &&f) const & {
1304 return expected_map_impl(*
this, std::forward<F>(f));
1307 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1308 std::declval<F &&>()))
1309 map(F &&f) const && {
1310 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1314 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1315 template <
class F> constexpr
auto transform(F &&f) & {
1316 return expected_map_impl(*
this, std::forward<F>(f));
1318 template <
class F> constexpr
auto transform(F &&f) && {
1319 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1321 template <
class F> constexpr
auto transform(F &&f)
const & {
1322 return expected_map_impl(*
this, std::forward<F>(f));
1324 template <
class F> constexpr
auto transform(F &&f)
const && {
1325 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1329 constexpr decltype(expected_map_impl(
1330 std::declval<expected &>(), std::declval<F &&>()))
1331 transform(F &&f) & {
1332 return expected_map_impl(*
this, std::forward<F>(f));
1335 constexpr decltype(expected_map_impl(std::declval<expected>(),
1336 std::declval<F &&>()))
1337 transform(F &&f) && {
1338 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1341 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1342 std::declval<F &&>()))
1343 transform(F &&f) const & {
1344 return expected_map_impl(*
this, std::forward<F>(f));
1347 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1348 std::declval<F &&>()))
1349 transform(F &&f) const && {
1350 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1354 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1355 template <
class F> constexpr
auto map_error(F &&f) & {
1356 return map_error_impl(*
this, std::forward<F>(f));
1358 template <
class F> constexpr
auto map_error(F &&f) && {
1359 return map_error_impl(std::move(*
this), std::forward<F>(f));
1361 template <
class F> constexpr
auto map_error(F &&f)
const & {
1362 return map_error_impl(*
this, std::forward<F>(f));
1364 template <
class F> constexpr
auto map_error(F &&f)
const && {
1365 return map_error_impl(std::move(*
this), std::forward<F>(f));
1369 constexpr decltype(map_error_impl(std::declval<expected &>(),
1370 std::declval<F &&>()))
1371 map_error(F &&f) & {
1372 return map_error_impl(*
this, std::forward<F>(f));
1375 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1376 std::declval<F &&>()))
1377 map_error(F &&f) && {
1378 return map_error_impl(std::move(*
this), std::forward<F>(f));
1381 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1382 std::declval<F &&>()))
1383 map_error(F &&f) const & {
1384 return map_error_impl(*
this, std::forward<F>(f));
1387 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1388 std::declval<F &&>()))
1389 map_error(F &&f) const && {
1390 return map_error_impl(std::move(*
this), std::forward<F>(f));
1393 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1394 template <
class F> constexpr
auto transform_error(F &&f) & {
1395 return map_error_impl(*
this, std::forward<F>(f));
1397 template <
class F> constexpr
auto transform_error(F &&f) && {
1398 return map_error_impl(std::move(*
this), std::forward<F>(f));
1400 template <
class F> constexpr
auto transform_error(F &&f)
const & {
1401 return map_error_impl(*
this, std::forward<F>(f));
1403 template <
class F> constexpr
auto transform_error(F &&f)
const && {
1404 return map_error_impl(std::move(*
this), std::forward<F>(f));
1408 constexpr decltype(map_error_impl(std::declval<expected &>(),
1409 std::declval<F &&>()))
1410 transform_error(F &&f) & {
1411 return map_error_impl(*
this, std::forward<F>(f));
1414 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1415 std::declval<F &&>()))
1416 transform_error(F &&f) && {
1417 return map_error_impl(std::move(*
this), std::forward<F>(f));
1420 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1421 std::declval<F &&>()))
1422 transform_error(F &&f) const & {
1423 return map_error_impl(*
this, std::forward<F>(f));
1426 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1427 std::declval<F &&>()))
1428 transform_error(F &&f) const && {
1429 return map_error_impl(std::move(*
this), std::forward<F>(f));
1432 template <
class F> expected constexpr or_else(F &&f) & {
1433 return or_else_impl(*
this, std::forward<F>(f));
1436 template <
class F> expected constexpr or_else(F &&f) && {
1437 return or_else_impl(std::move(*
this), std::forward<F>(f));
1440 template <
class F> expected constexpr or_else(F &&f)
const & {
1441 return or_else_impl(*
this, std::forward<F>(f));
1444 template <
class F> expected constexpr or_else(F &&f)
const && {
1445 return or_else_impl(std::move(*
this), std::forward<F>(f));
1448 constexpr expected() =
default;
1449 constexpr expected(
const expected &rhs) =
default;
1450 constexpr expected(expected &&rhs) =
default;
1451 expected &operator=(
const expected &rhs) =
default;
1452 expected &operator=(expected &&rhs) =
default;
1454 template <
class... Args,
1455 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1457 constexpr expected(in_place_t, Args &&...args)
1458 : impl_base(in_place, std::forward<Args>(args)...),
1459 ctor_base(detail::default_constructor_tag{}) {}
1461 template <
class U,
class... Args,
1462 detail::enable_if_t<std::is_constructible<
1463 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1464 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1465 : impl_base(in_place, il, std::forward<Args>(args)...),
1466 ctor_base(detail::default_constructor_tag{}) {}
1468 template <
class G = E,
1469 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1471 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1473 explicit constexpr expected(
const unexpected<G> &e)
1474 : impl_base(unexpect, e.value()),
1475 ctor_base(detail::default_constructor_tag{}) {}
1479 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1481 detail::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1482 constexpr expected(unexpected<G>
const &e)
1483 : impl_base(unexpect, e.value()),
1484 ctor_base(detail::default_constructor_tag{}) {}
1488 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1489 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1490 explicit constexpr expected(unexpected<G> &&e) noexcept(
1491 std::is_nothrow_constructible<E, G &&>::value)
1492 : impl_base(unexpect, std::move(e.value())),
1493 ctor_base(detail::default_constructor_tag{}) {}
1497 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1498 detail::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1499 constexpr expected(unexpected<G> &&e) noexcept(
1500 std::is_nothrow_constructible<E, G &&>::value)
1501 : impl_base(unexpect, std::move(e.value())),
1502 ctor_base(detail::default_constructor_tag{}) {}
1504 template <
class... Args,
1505 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1507 constexpr
explicit expected(unexpect_t, Args &&...args)
1508 : impl_base(unexpect, std::forward<Args>(args)...),
1509 ctor_base(detail::default_constructor_tag{}) {}
1511 template <
class U,
class... Args,
1512 detail::enable_if_t<std::is_constructible<
1513 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1514 constexpr
explicit expected(unexpect_t, std::initializer_list<U> il,
1516 : impl_base(unexpect, il, std::forward<Args>(args)...),
1517 ctor_base(detail::default_constructor_tag{}) {}
1519 template <
class U,
class G,
1520 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1521 std::is_convertible<G const &, E>::value)> * =
1523 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1525 explicit constexpr expected(
const expected<U, G> &rhs)
1526 : ctor_base(detail::default_constructor_tag{}) {
1527 if (rhs.has_value()) {
1528 this->construct(*rhs);
1530 this->construct_error(rhs.error());
1534 template <
class U,
class G,
1535 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1536 std::is_convertible<G const &, E>::value)> * =
1538 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1540 constexpr expected(
const expected<U, G> &rhs)
1541 : ctor_base(detail::default_constructor_tag{}) {
1542 if (rhs.has_value()) {
1543 this->construct(*rhs);
1545 this->construct_error(rhs.error());
1551 detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1552 std::is_convertible<G &&, E>::value)> * =
nullptr,
1553 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1554 explicit constexpr expected(expected<U, G> &&rhs)
1555 : ctor_base(detail::default_constructor_tag{}) {
1556 if (rhs.has_value()) {
1557 this->construct(std::move(*rhs));
1559 this->construct_error(std::move(rhs.error()));
1565 detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1566 std::is_convertible<G &&, E>::value)> * =
nullptr,
1567 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1568 constexpr expected(expected<U, G> &&rhs)
1569 : ctor_base(detail::default_constructor_tag{}) {
1570 if (rhs.has_value()) {
1571 this->construct(std::move(*rhs));
1573 this->construct_error(std::move(rhs.error()));
1579 detail::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1580 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1581 explicit constexpr expected(U &&v)
1582 : expected(in_place, std::forward<U>(v)) {}
1586 detail::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1587 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1588 constexpr expected(U &&v)
1589 : expected(in_place, std::forward<U>(v)) {}
1592 class U = T,
class G = T,
1593 detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1595 detail::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1596 detail::enable_if_t<
1597 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1598 !detail::conjunction<std::is_scalar<T>,
1599 std::is_same<T, detail::decay_t<U>>>::value &&
1600 std::is_constructible<T, U>::value &&
1601 std::is_assignable<G &, U>::value &&
1602 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1603 expected &
operator=(U &&v) {
1605 val() = std::forward<U>(v);
1607 err().~unexpected<E>();
1608 ::new (valptr()) T(std::forward<U>(v));
1609 this->m_has_val = true;
1616 class U = T, class G = T,
1617 detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
1619 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr,
1620 detail::enable_if_t<
1621 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1622 !detail::conjunction<std::is_scalar<T>,
1623 std::is_same<T, detail::decay_t<U>>>::value &&
1624 std::is_constructible<T, U>::value &&
1625 std::is_assignable<G &, U>::value &&
1626 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1627 expected &operator=(U &&v) {
1629 val() = std::forward<U>(v);
1631 auto tmp = std::move(err());
1632 err().~unexpected<E>();
1634 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1636 ::new (valptr()) T(std::forward<U>(v));
1637 this->m_has_val = true;
1639 err() = std::move(tmp);
1643 ::new (valptr()) T(std::forward<U>(v));
1644 this->m_has_val = true;
1651 template <
class G = E,
1652 detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1653 std::is_assignable<G &, G>::value> * =
nullptr>
1654 expected &operator=(
const unexpected<G> &rhs) {
1658 this->destroy_val();
1659 ::new (errptr()) unexpected<E>(rhs);
1660 this->m_has_val = false;
1666 template <class G = E,
1667 detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1668 std::is_move_assignable<G>::value> * =
nullptr>
1669 expected &operator=(unexpected<G> &&rhs) noexcept {
1671 err() = std::move(rhs);
1673 this->destroy_val();
1674 ::new (errptr()) unexpected<E>(std::move(rhs));
1675 this->m_has_val = false;
1681 template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1682 T, Args &&...>::value> * =
nullptr>
1683 void emplace(Args &&...args) {
1687 err().~unexpected<E>();
1688 this->m_has_val =
true;
1690 ::new (valptr()) T(std::forward<Args>(args)...);
1693 template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1694 T, Args &&...>::value> * =
nullptr>
1695 void emplace(Args &&...args) {
1698 ::new (valptr()) T(std::forward<Args>(args)...);
1700 auto tmp = std::move(err());
1701 err().~unexpected<E>();
1703 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1705 ::new (valptr()) T(std::forward<Args>(args)...);
1706 this->m_has_val = true;
1708 err() = std::move(tmp);
1712 ::new (valptr()) T(std::forward<Args>(args)...);
1713 this->m_has_val = true;
1718 template <
class U,
class... Args,
1719 detail::enable_if_t<std::is_nothrow_constructible<
1720 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1721 void emplace(std::initializer_list<U> il, Args &&...args) {
1723 T t(il, std::forward<Args>(args)...);
1724 val() = std::move(t);
1726 err().~unexpected<E>();
1727 ::new (valptr()) T(il, std::forward<Args>(args)...);
1728 this->m_has_val = true;
1732 template <class U, class... Args,
1733 detail::enable_if_t<!std::is_nothrow_constructible<
1734 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1735 void emplace(std::initializer_list<U> il, Args &&...args) {
1737 T t(il, std::forward<Args>(args)...);
1738 val() = std::move(t);
1740 auto tmp = std::move(err());
1741 err().~unexpected<E>();
1743 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1745 ::new (valptr()) T(il, std::forward<Args>(args)...);
1746 this->m_has_val = true;
1748 err() = std::move(tmp);
1752 ::new (valptr()) T(il, std::forward<Args>(args)...);
1753 this->m_has_val = true;
1759 using t_is_void = std::true_type;
1760 using t_is_not_void = std::false_type;
1761 using t_is_nothrow_move_constructible = std::true_type;
1762 using move_constructing_t_can_throw = std::false_type;
1763 using e_is_nothrow_move_constructible = std::true_type;
1764 using move_constructing_e_can_throw = std::false_type;
1766 void swap_where_both_have_value(expected & , t_is_void) noexcept {
1770 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1772 swap(val(), rhs.val());
1775 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1776 std::is_nothrow_move_constructible<E>::value) {
1777 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1778 rhs.err().~unexpected_type();
1779 std::
swap(this->m_has_val, rhs.m_has_val);
1782 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1783 swap_where_only_one_has_value_and_t_is_not_void(
1784 rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1785 typename std::is_nothrow_move_constructible<E>::type{});
1788 void swap_where_only_one_has_value_and_t_is_not_void(
1789 expected &rhs, t_is_nothrow_move_constructible,
1790 e_is_nothrow_move_constructible) noexcept {
1791 auto temp = std::move(val());
1793 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1794 rhs.err().~unexpected_type();
1795 ::new (rhs.valptr()) T(std::move(temp));
1796 std::
swap(this->m_has_val, rhs.m_has_val);
1799 void swap_where_only_one_has_value_and_t_is_not_void(
1800 expected &rhs, t_is_nothrow_move_constructible,
1801 move_constructing_e_can_throw) {
1802 auto temp = std::move(val());
1804 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1806 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1807 rhs.err().~unexpected_type();
1808 ::new (rhs.valptr()) T(std::move(temp));
1809 std::
swap(this->m_has_val, rhs.m_has_val);
1811 val() = std::move(temp);
1815 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1816 rhs.err().~unexpected_type();
1817 ::new (rhs.valptr()) T(std::move(temp));
1818 std::
swap(this->m_has_val, rhs.m_has_val);
1822 void swap_where_only_one_has_value_and_t_is_not_void(
1823 expected &rhs, move_constructing_t_can_throw,
1824 e_is_nothrow_move_constructible) {
1825 auto temp = std::move(rhs.err());
1826 rhs.err().~unexpected_type();
1827 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1829 ::new (rhs.valptr()) T(std::move(val()));
1831 ::new (errptr()) unexpected_type(std::move(temp));
1832 std::
swap(this->m_has_val, rhs.m_has_val);
1834 rhs.err() = std::move(temp);
1838 ::new (rhs.valptr()) T(std::move(val()));
1840 ::new (errptr()) unexpected_type(std::move(temp));
1841 std::
swap(this->m_has_val, rhs.m_has_val);
1846 template <
class OT = T,
class OE = E>
1847 detail::enable_if_t<detail::is_swappable<OT>::value &&
1848 detail::is_swappable<OE>::value &&
1849 (std::is_nothrow_move_constructible<OT>::value ||
1850 std::is_nothrow_move_constructible<OE>::value)>
1851 swap(expected &rhs) noexcept(
1852 std::is_nothrow_move_constructible<T>::value
1853 &&detail::is_nothrow_swappable<T>::value
1854 &&std::is_nothrow_move_constructible<E>::value
1855 &&detail::is_nothrow_swappable<E>::value) {
1856 if (has_value() && rhs.has_value()) {
1857 swap_where_both_have_value(rhs,
typename std::is_void<T>::type{});
1858 }
else if (!has_value() && rhs.has_value()) {
1860 }
else if (has_value()) {
1861 swap_where_only_one_has_value(rhs,
typename std::is_void<T>::type{});
1864 swap(err(), rhs.err());
1868 constexpr
const T *operator->()
const {
1869 assert(has_value());
1872 constexpr T *operator->() {
1873 assert(has_value());
1877 template <
class U = T,
1878 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1879 constexpr
const U &operator*() const & {
1880 assert(has_value());
1883 template <
class U = T,
1884 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1885 constexpr U &operator*() & {
1886 assert(has_value());
1889 template <
class U = T,
1890 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1891 constexpr
const U &&operator*() const && {
1892 assert(has_value());
1893 return std::move(val());
1895 template <
class U = T,
1896 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1897 constexpr U &&operator*() && {
1898 assert(has_value());
1899 return std::move(val());
1902 constexpr
bool has_value() const noexcept {
return this->m_has_val; }
1903 constexpr
explicit operator bool() const noexcept {
return this->m_has_val; }
1905 template <
class U = T,
1906 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1907 constexpr
const U &value() const & {
1909 detail::throw_exception(bad_expected_access<E>(err().value()));
1912 template <
class U = T,
1913 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1914 constexpr U &value() & {
1916 detail::throw_exception(bad_expected_access<E>(err().value()));
1919 template <
class U = T,
1920 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1921 constexpr
const U &&value() const && {
1923 detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1924 return std::move(val());
1926 template <
class U = T,
1927 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1928 constexpr U &&value() && {
1930 detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1931 return std::move(val());
1934 constexpr
const E &error() const & {
1935 assert(!has_value());
1936 return err().value();
1938 constexpr E &error() & {
1939 assert(!has_value());
1940 return err().value();
1942 constexpr
const E &&error() const && {
1943 assert(!has_value());
1944 return std::move(err().value());
1946 constexpr E &&error() && {
1947 assert(!has_value());
1948 return std::move(err().value());
1951 template <
class U> constexpr T value_or(U &&v)
const & {
1952 static_assert(std::is_copy_constructible<T>::value &&
1953 std::is_convertible<U &&, T>::value,
1954 "T must be copy-constructible and convertible to from U&&");
1955 return bool(*
this) ? **this :
static_cast<T
>(std::forward<U>(v));
1957 template <
class U> constexpr T value_or(U &&v) && {
1958 static_assert(std::is_move_constructible<T>::value &&
1959 std::is_convertible<U &&, T>::value,
1960 "T must be move-constructible and convertible to from U&&");
1961 return bool(*
this) ? std::move(**
this) : static_cast<T>(std::forward<U>(v));
1966 template <
class Exp>
using exp_t =
typename detail::decay_t<Exp>::value_type;
1967 template <
class Exp>
using err_t =
typename detail::decay_t<Exp>::error_type;
1968 template <
class Exp,
class Ret>
using ret_t = expected<Ret, err_t<Exp>>;
1970 template <
class Exp,
class F,
1971 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1972 class Ret = decltype(detail::invoke(std::declval<F>(),
1973 *std::declval<Exp>()))>
1974 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1975 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1977 return exp.has_value()
1978 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
1979 : Ret(unexpect, std::forward<Exp>(exp).error());
1982 template <
class Exp,
class F,
1983 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
1984 class Ret = decltype(detail::invoke(std::declval<F>()))>
1985 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1986 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1988 return exp.has_value() ? detail::invoke(std::forward<F>(f))
1989 : Ret(unexpect, std::forward<Exp>(exp).error());
1992 template <
class Exp,
class F,
1993 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1994 class Ret = decltype(detail::invoke(std::declval<F>(),
1995 *std::declval<Exp>())),
1996 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1997 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
1998 using result = ret_t<Exp, detail::decay_t<Ret>>;
1999 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2000 *std::forward<Exp>(exp)))
2001 : result(unexpect, std::forward<Exp>(exp).error());
2004 template <
class Exp,
class F,
2005 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2006 class Ret = decltype(detail::invoke(std::declval<F>(),
2007 *std::declval<Exp>())),
2008 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2009 auto expected_map_impl(Exp &&exp, F &&f) {
2010 using result = expected<void, err_t<Exp>>;
2011 if (exp.has_value()) {
2012 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2016 return result(unexpect, std::forward<Exp>(exp).error());
2019 template <
class Exp,
class F,
2020 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2021 class Ret = decltype(detail::invoke(std::declval<F>())),
2022 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2023 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
2024 using result = ret_t<Exp, detail::decay_t<Ret>>;
2025 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2026 : result(unexpect, std::forward<Exp>(exp).error());
2029 template <
class Exp,
class F,
2030 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2031 class Ret = decltype(detail::invoke(std::declval<F>())),
2032 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2033 auto expected_map_impl(Exp &&exp, F &&f) {
2034 using result = expected<void, err_t<Exp>>;
2035 if (exp.has_value()) {
2036 detail::invoke(std::forward<F>(f));
2040 return result(unexpect, std::forward<Exp>(exp).error());
2043 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
2044 template <
class Exp,
class F,
2045 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2046 class Ret = decltype(detail::invoke(std::declval<F>(),
2047 std::declval<Exp>().error())),
2048 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2049 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2050 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2051 return exp.has_value()
2052 ? result(*std::forward<Exp>(exp))
2053 : result(unexpect, detail::invoke(std::forward<F>(f),
2054 std::forward<Exp>(exp).error()));
2056 template <
class Exp,
class F,
2057 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2058 class Ret = decltype(detail::invoke(std::declval<F>(),
2059 std::declval<Exp>().error())),
2060 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2061 auto map_error_impl(Exp &&exp, F &&f) {
2062 using result = expected<exp_t<Exp>, monostate>;
2063 if (exp.has_value()) {
2064 return result(*std::forward<Exp>(exp));
2067 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2068 return result(unexpect, monostate{});
2070 template <
class Exp,
class F,
2071 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2072 class Ret = decltype(detail::invoke(std::declval<F>(),
2073 std::declval<Exp>().error())),
2074 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2075 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2076 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2077 return exp.has_value()
2079 : result(unexpect, detail::invoke(std::forward<F>(f),
2080 std::forward<Exp>(exp).error()));
2082 template <
class Exp,
class F,
2083 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2084 class Ret = decltype(detail::invoke(std::declval<F>(),
2085 std::declval<Exp>().error())),
2086 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2087 auto map_error_impl(Exp &&exp, F &&f) {
2088 using result = expected<exp_t<Exp>, monostate>;
2089 if (exp.has_value()) {
2093 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2094 return result(unexpect, monostate{});
2097 template <
class Exp,
class F,
2098 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2099 class Ret = decltype(detail::invoke(std::declval<F>(),
2100 std::declval<Exp>().error())),
2101 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2102 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2103 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2104 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2106 return exp.has_value()
2107 ? result(*std::forward<Exp>(exp))
2108 : result(unexpect, detail::invoke(std::forward<F>(f),
2109 std::forward<Exp>(exp).error()));
2112 template <
class Exp,
class F,
2113 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2114 class Ret = decltype(detail::invoke(std::declval<F>(),
2115 std::declval<Exp>().error())),
2116 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2117 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2118 using result = expected<exp_t<Exp>, monostate>;
2119 if (exp.has_value()) {
2120 return result(*std::forward<Exp>(exp));
2123 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2124 return result(unexpect, monostate{});
2127 template <
class Exp,
class F,
2128 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2129 class Ret = decltype(detail::invoke(std::declval<F>(),
2130 std::declval<Exp>().error())),
2131 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2132 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2133 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2134 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2136 return exp.has_value()
2138 : result(unexpect, detail::invoke(std::forward<F>(f),
2139 std::forward<Exp>(exp).error()));
2142 template <
class Exp,
class F,
2143 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2144 class Ret = decltype(detail::invoke(std::declval<F>(),
2145 std::declval<Exp>().error())),
2146 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2147 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2148 using result = expected<exp_t<Exp>, monostate>;
2149 if (exp.has_value()) {
2153 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2154 return result(unexpect, monostate{});
2158 template <
class Exp,
class F,
2159 class Ret = decltype(detail::invoke(std::declval<F>(),
2160 std::declval<Exp>().error())),
2161 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2162 constexpr
auto or_else_impl(Exp &&exp, F &&f) {
2163 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2164 return exp.has_value() ? std::forward<Exp>(exp)
2165 : detail::invoke(std::forward<F>(f),
2166 std::forward<Exp>(exp).error());
2169 template <
class Exp,
class F,
2170 class Ret = decltype(detail::invoke(std::declval<F>(),
2171 std::declval<Exp>().error())),
2172 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2173 detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2174 return exp.has_value() ? std::forward<Exp>(exp)
2175 : (detail::invoke(std::forward<F>(f),
2176 std::forward<Exp>(exp).error()),
2177 std::forward<Exp>(exp));
2182 template <
class T,
class E,
class U,
class F>
2183 constexpr
bool operator==(
const expected<T, E> &lhs,
2184 const expected<U, F> &rhs) {
2185 return (lhs.has_value() != rhs.has_value())
2187 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2189 template <
class T,
class E,
class U,
class F>
2190 constexpr
bool operator!=(
const expected<T, E> &lhs,
2191 const expected<U, F> &rhs) {
2192 return (lhs.has_value() != rhs.has_value())
2194 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2196 template <
class E,
class F>
2197 constexpr
bool operator==(
const expected<void, E> &lhs,
2198 const expected<void, F> &rhs) {
2199 return (lhs.has_value() != rhs.has_value())
2201 : (!lhs.has_value() ? lhs.error() == rhs.error() :
true);
2203 template <
class E,
class F>
2204 constexpr
bool operator!=(
const expected<void, E> &lhs,
2205 const expected<void, F> &rhs) {
2206 return (lhs.has_value() != rhs.has_value())
2208 : (!lhs.has_value() ? lhs.error() == rhs.error() :
false);
2211 template <
class T,
class E,
class U>
2212 constexpr
bool operator==(
const expected<T, E> &x,
const U &v) {
2213 return x.has_value() ? *x == v :
false;
2215 template <
class T,
class E,
class U>
2216 constexpr
bool operator==(
const U &v,
const expected<T, E> &x) {
2217 return x.has_value() ? *x == v :
false;
2219 template <
class T,
class E,
class U>
2220 constexpr
bool operator!=(
const expected<T, E> &x,
const U &v) {
2221 return x.has_value() ? *x != v :
true;
2223 template <
class T,
class E,
class U>
2224 constexpr
bool operator!=(
const U &v,
const expected<T, E> &x) {
2225 return x.has_value() ? *x != v :
true;
2228 template <
class T,
class E>
2229 constexpr
bool operator==(
const expected<T, E> &x,
const unexpected<E> &e) {
2230 return x.has_value() ? false : x.error() == e.value();
2232 template <
class T,
class E>
2233 constexpr
bool operator==(
const unexpected<E> &e,
const expected<T, E> &x) {
2234 return x.has_value() ? false : x.error() == e.value();
2236 template <
class T,
class E>
2237 constexpr
bool operator!=(
const expected<T, E> &x,
const unexpected<E> &e) {
2238 return x.has_value() ? true : x.error() != e.value();
2240 template <
class T,
class E>
2241 constexpr
bool operator!=(
const unexpected<E> &e,
const expected<T, E> &x) {
2242 return x.has_value() ? true : x.error() != e.value();
2245 template <
class T,
class E,
2246 detail::enable_if_t<(std::is_void<T>::value ||
2247 std::is_move_constructible<T>::value) &&
2248 detail::is_swappable<T>::value &&
2249 std::is_move_constructible<E>::value &&
2250 detail::is_swappable<E>::value> * =
nullptr>
2251 void swap(expected<T, E> &lhs,
2252 expected<T, E> &rhs) noexcept(noexcept(lhs.swap(rhs))) {
The exception thrown by gul14::expected if value() is called, but no value is present.
Definition: expected.h:49
An expected<T, E> is an object that normally contains an "expected" object of type T,...
Definition: expected.h:87
Class template for constructing the unexpected value of an expected object.
Definition: expected.h:95
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
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:1649
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:538
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.