25 #ifndef GUL14_EXPECTED_H_
26 #define GUL14_EXPECTED_H_
31 #include <type_traits>
92 template <
typename T,
typename E>
100 template <
typename E>
105 #if defined(__EXCEPTIONS) || defined(_CPPUNWIND)
106 #define GUL14_EXPECTED_EXCEPTIONS_ENABLED
109 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
110 #define GUL14_EXPECTED_GCC54
113 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
114 #define GUL14_EXPECTED_GCC55
117 #if (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
118 #ifndef GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
119 #define GUL14_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
122 struct is_trivially_copy_constructible
123 : std::is_trivially_copy_constructible<T> {};
124 #ifdef _GLIBCXX_VECTOR
125 template <
class T,
class A>
126 struct is_trivially_copy_constructible<std::vector<T, A>> : std::false_type {};
131 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
132 gul14::detail::is_trivially_copy_constructible<T>
133 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
134 std::is_trivially_copy_assignable<T>
135 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
136 std::is_trivially_destructible<T>
138 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
139 std::is_trivially_copy_constructible<T>
140 #define GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
141 std::is_trivially_copy_assignable<T>
142 #define GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T) \
143 std::is_trivially_destructible<T>
146 template <
class T,
class E>
class expected;
152 static_assert(!std::is_same<E, void>::value,
"E must not be void");
154 unexpected() =
delete;
155 constexpr
explicit unexpected(
const E &e) : m_val(e) {}
157 constexpr
explicit unexpected(E &&e) : m_val(std::move(e)) {}
159 template <
class... Args,
typename std::enable_if<std::is_constructible<
160 E, Args &&...>::value>::type * =
nullptr>
161 constexpr
explicit unexpected(Args &&...args)
162 : m_val(std::forward<Args>(args)...) {}
164 class U,
class... Args,
165 typename std::enable_if<std::is_constructible<
166 E, std::initializer_list<U> &, Args &&...>::value>::type * =
nullptr>
167 constexpr
explicit unexpected(std::initializer_list<U> l, Args &&...args)
168 : m_val(l, std::forward<Args>(args)...) {}
170 constexpr
const E &value() const & {
return m_val; }
171 constexpr E &value() & {
return m_val; }
172 constexpr E &&value() && {
return std::move(m_val); }
173 constexpr
const E &&value() const && {
return std::move(m_val); }
179 #ifdef __cpp_deduction_guides
180 template <
class E> unexpected(E) -> unexpected<E>;
184 constexpr
bool operator==(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
185 return lhs.value() == rhs.value();
188 constexpr
bool operator!=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
189 return lhs.value() != rhs.value();
192 constexpr
bool operator<(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
193 return lhs.value() < rhs.value();
196 constexpr
bool operator<=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
197 return lhs.value() <= rhs.value();
200 constexpr
bool operator>(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
201 return lhs.value() > rhs.value();
204 constexpr
bool operator>=(
const unexpected<E> &lhs,
const unexpected<E> &rhs) {
205 return lhs.value() >= rhs.value();
209 unexpected<typename std::decay<E>::type> make_unexpected(E &&e) {
210 return unexpected<typename std::decay<E>::type>(std::forward<E>(e));
214 unexpect_t() =
default;
216 static constexpr unexpect_t unexpect{};
219 template <
typename E>
220 [[noreturn]] constexpr
void throw_exception(E &&e) {
221 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
222 throw std::forward<E>(e);
228 __builtin_unreachable();
233 #ifndef GUL14_TRAITS_MUTEX
234 #define GUL14_TRAITS_MUTEX
236 template <
class T>
using remove_const_t =
typename std::remove_const<T>::type;
238 using remove_reference_t =
typename std::remove_reference<T>::type;
239 template <
class T>
using decay_t =
typename std::decay<T>::type;
240 template <
bool E,
class T =
void>
241 using enable_if_t =
typename std::enable_if<E, T>::type;
242 template <
bool B,
class T,
class F>
243 using conditional_t =
typename std::conditional<B, T, F>::type;
246 template <
class...>
struct conjunction : std::true_type {};
247 template <
class B>
struct conjunction<B> : B {};
248 template <
class B,
class... Bs>
249 struct conjunction<B, Bs...>
250 : std::conditional<bool(B::value), conjunction<Bs...>, B>::type {};
255 typename Fn,
typename... Args,
256 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>,
int = 0>
257 constexpr
auto invoke(Fn &&f, Args &&...args) noexcept(
258 noexcept(std::mem_fn(f)(std::forward<Args>(args)...)))
259 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) {
260 return std::mem_fn(f)(std::forward<Args>(args)...);
263 template <
typename Fn,
typename... Args,
264 typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>>
265 constexpr
auto invoke(Fn &&f, Args &&...args) noexcept(
266 noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...)))
267 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) {
268 return std::forward<Fn>(f)(std::forward<Args>(args)...);
272 template <
class F,
class,
class... Us>
struct invoke_result_impl;
274 template <
class F,
class... Us>
275 struct invoke_result_impl<
277 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()),
280 decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...));
283 template <
class F,
class... Us>
284 using invoke_result = invoke_result_impl<F, void, Us...>;
286 template <
class F,
class... Us>
287 using invoke_result_t =
typename invoke_result<F, Us...>::type;
290 namespace swap_adl_tests {
294 template <
class T> tag
swap(T &, T &);
295 template <
class T, std::
size_t N> tag
swap(T (&a)[N], T (&b)[N]);
299 template <
class,
class> std::false_type can_swap(...) noexcept(false);
300 template <class T, class U,
301 class = decltype(
swap(std::declval<T &>(), std::declval<U &>()))>
302 std::true_type can_swap(
int) noexcept(noexcept(
swap(std::declval<T &>(),
303 std::declval<U &>())));
305 template <class, class> std::false_type uses_std(...);
306 template <class T, class U>
307 std::is_same<decltype(
swap(std::declval<T &>(), std::declval<U &>())), tag>
311 struct is_std_swap_noexcept
312 : std::integral_constant<
bool,
313 std::is_nothrow_move_constructible<T>::value &&
314 std::is_nothrow_move_assignable<T>::value> {};
316 template <
class T, std::
size_t N>
317 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
319 template <
class T,
class U>
320 struct is_adl_swap_noexcept
321 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
324 template <
class T,
class U = T>
326 : std::integral_constant<
328 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
329 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
330 (std::is_move_assignable<T>::value &&
331 std::is_move_constructible<T>::value))> {};
333 template <
class T, std::
size_t N>
334 struct is_swappable<T[N], T[N]>
335 : std::integral_constant<
337 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
338 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
340 is_swappable<T, T>::value)> {};
342 template <
class T,
class U = T>
343 struct is_nothrow_swappable
344 : std::integral_constant<
346 is_swappable<T, U>::value &&
347 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
348 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
349 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
350 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
354 template <
class T>
struct is_expected_impl : std::false_type {};
355 template <
class T,
class E>
356 struct is_expected_impl<expected<T, E>> : std::true_type {};
357 template <
class T>
using is_expected = is_expected_impl<decay_t<T>>;
359 template <
class T,
class E,
class U>
360 using expected_enable_forward_value = detail::enable_if_t<
361 std::is_constructible<T, U &&>::value &&
362 !std::is_same<detail::decay_t<U>, in_place_t>::value &&
363 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
364 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
366 template <
class T,
class E,
class U,
class G,
class UR,
class GR>
367 using expected_enable_from_other = detail::enable_if_t<
368 std::is_constructible<T, UR>::value &&
369 std::is_constructible<E, GR>::value &&
370 !std::is_constructible<T, expected<U, G> &>::value &&
371 !std::is_constructible<T, expected<U, G> &&>::value &&
372 !std::is_constructible<T, const expected<U, G> &>::value &&
373 !std::is_constructible<T, const expected<U, G> &&>::value &&
374 !std::is_convertible<expected<U, G> &, T>::value &&
375 !std::is_convertible<expected<U, G> &&, T>::value &&
376 !std::is_convertible<const expected<U, G> &, T>::value &&
377 !std::is_convertible<const expected<U, G> &&, T>::value>;
379 template <
class T,
class U>
380 using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
383 using is_copy_constructible_or_void =
384 is_void_or<T, std::is_copy_constructible<T>>;
387 using is_move_constructible_or_void =
388 is_void_or<T, std::is_move_constructible<T>>;
391 using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
394 using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
397 static constexpr no_init_t no_init{};
405 template <class T, class E, bool = std::is_trivially_destructible<T>::value,
406 bool = std::is_trivially_destructible<E>::value>
407 struct expected_storage_base {
408 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
409 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
411 template <
class... Args,
412 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
414 constexpr expected_storage_base(in_place_t, Args &&...args)
415 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
417 template <
class U,
class... Args,
418 detail::enable_if_t<std::is_constructible<
419 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
420 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
422 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
423 template <
class... Args,
424 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
426 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
427 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
429 template <
class U,
class... Args,
430 detail::enable_if_t<std::is_constructible<
431 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
432 constexpr
explicit expected_storage_base(unexpect_t,
433 std::initializer_list<U> il,
435 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
437 ~expected_storage_base() {
441 m_unexpect.~unexpected<E>();
446 unexpected<E> m_unexpect;
454 template <
class T,
class E>
struct expected_storage_base<T, E, true, true> {
455 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
456 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
458 template <
class... Args,
459 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
461 constexpr expected_storage_base(in_place_t, Args &&...args)
462 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
464 template <
class U,
class... Args,
465 detail::enable_if_t<std::is_constructible<
466 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
467 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
469 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
470 template <
class... Args,
471 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
473 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
474 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
476 template <
class U,
class... Args,
477 detail::enable_if_t<std::is_constructible<
478 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
479 constexpr
explicit expected_storage_base(unexpect_t,
480 std::initializer_list<U> il,
482 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
484 ~expected_storage_base() =
default;
487 unexpected<E> m_unexpect;
494 template <
class T,
class E>
struct expected_storage_base<T, E, true, false> {
495 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
496 constexpr expected_storage_base(no_init_t)
497 : m_no_init(), m_has_val(false) {}
499 template <
class... Args,
500 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
502 constexpr expected_storage_base(in_place_t, Args &&...args)
503 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
505 template <
class U,
class... Args,
506 detail::enable_if_t<std::is_constructible<
507 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
508 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
510 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
511 template <
class... Args,
512 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
514 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
515 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
517 template <
class U,
class... Args,
518 detail::enable_if_t<std::is_constructible<
519 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
520 constexpr
explicit expected_storage_base(unexpect_t,
521 std::initializer_list<U> il,
523 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
525 ~expected_storage_base() {
527 m_unexpect.~unexpected<E>();
533 unexpected<E> m_unexpect;
540 template <
class T,
class E>
struct expected_storage_base<T, E, false, true> {
541 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
542 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
544 template <
class... Args,
545 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
547 constexpr expected_storage_base(in_place_t, Args &&...args)
548 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
550 template <
class U,
class... Args,
551 detail::enable_if_t<std::is_constructible<
552 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
553 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
555 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
556 template <
class... Args,
557 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
559 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
560 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
562 template <
class U,
class... Args,
563 detail::enable_if_t<std::is_constructible<
564 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
565 constexpr
explicit expected_storage_base(unexpect_t,
566 std::initializer_list<U> il,
568 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
570 ~expected_storage_base() {
577 unexpected<E> m_unexpect;
584 template <
class E>
struct expected_storage_base<void, E, false, true> {
590 expected_storage_base() : m_has_val(true) {}
592 constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
594 constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
596 template <
class... Args,
597 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
599 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
600 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
602 template <
class U,
class... Args,
603 detail::enable_if_t<std::is_constructible<
604 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
605 constexpr
explicit expected_storage_base(unexpect_t,
606 std::initializer_list<U> il,
608 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
610 ~expected_storage_base() =
default;
613 unexpected<E> m_unexpect;
620 template <
class E>
struct expected_storage_base<void, E, false, false> {
621 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
622 constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
624 constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
626 template <
class... Args,
627 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
629 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
630 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
632 template <
class U,
class... Args,
633 detail::enable_if_t<std::is_constructible<
634 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
635 constexpr
explicit expected_storage_base(unexpect_t,
636 std::initializer_list<U> il,
638 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
640 ~expected_storage_base() {
642 m_unexpect.~unexpected<E>();
647 unexpected<E> m_unexpect;
655 template <
class T,
class E>
656 struct expected_operations_base : expected_storage_base<T, E> {
657 using expected_storage_base<T, E>::expected_storage_base;
659 template <
class... Args>
void construct(Args &&...args) noexcept {
660 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
661 this->m_has_val =
true;
664 template <
class Rhs>
void construct_with(Rhs &&rhs) noexcept {
665 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
666 this->m_has_val =
true;
669 template <
class... Args>
void construct_error(Args &&...args) noexcept {
670 new (std::addressof(this->m_unexpect))
671 unexpected<E>(std::forward<Args>(args)...);
672 this->m_has_val =
false;
675 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
683 template <
class U = T,
684 detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
686 void assign(
const expected_operations_base &rhs) noexcept {
687 if (!this->m_has_val && rhs.m_has_val) {
688 geterr().~unexpected<E>();
689 construct(rhs.get());
697 template <
class U = T,
698 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
699 std::is_nothrow_move_constructible<U>::value>
701 void assign(
const expected_operations_base &rhs) noexcept {
702 if (!this->m_has_val && rhs.m_has_val) {
704 geterr().~unexpected<E>();
705 construct(std::move(tmp));
716 template <
class U = T,
717 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
718 !std::is_nothrow_move_constructible<U>::value>
720 void assign(
const expected_operations_base &rhs) {
721 if (!this->m_has_val && rhs.m_has_val) {
722 auto tmp = std::move(geterr());
723 geterr().~unexpected<E>();
725 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
727 construct(rhs.get());
729 geterr() = std::move(tmp);
733 construct(rhs.get());
741 template <
class U = T,
742 detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
744 void assign(expected_operations_base &&rhs) noexcept {
745 if (!this->m_has_val && rhs.m_has_val) {
746 geterr().~unexpected<E>();
747 construct(std::move(rhs).
get());
749 assign_common(std::move(rhs));
753 template <
class U = T,
754 detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
756 void assign(expected_operations_base &&rhs) {
757 if (!this->m_has_val && rhs.m_has_val) {
758 auto tmp = std::move(geterr());
759 geterr().~unexpected<E>();
760 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
762 construct(std::move(rhs).
get());
764 geterr() = std::move(tmp);
768 construct(std::move(rhs).
get());
771 assign_common(std::move(rhs));
778 void assign(
const expected_operations_base &rhs) noexcept {
779 if (!this->m_has_val && rhs.m_has_val) {
780 geterr().~unexpected<E>();
781 construct(rhs.get());
787 void assign(expected_operations_base &&rhs) noexcept {
788 if (!this->m_has_val && rhs.m_has_val) {
789 geterr().~unexpected<E>();
790 construct(std::move(rhs).
get());
792 assign_common(std::move(rhs));
799 template <
class Rhs>
void assign_common(Rhs &&rhs) {
800 if (this->m_has_val) {
802 get() = std::forward<Rhs>(rhs).get();
805 construct_error(std::forward<Rhs>(rhs).geterr());
808 if (!rhs.m_has_val) {
809 geterr() = std::forward<Rhs>(rhs).geterr();
814 bool has_value()
const {
return this->m_has_val; }
816 constexpr T &
get() & {
return this->m_val; }
817 constexpr
const T &
get() const & {
return this->m_val; }
818 constexpr T &&
get() && {
return std::move(this->m_val); }
819 constexpr
const T &&
get() const && {
return std::move(this->m_val); }
821 constexpr unexpected<E> &geterr() & {
822 return this->m_unexpect;
824 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
825 constexpr unexpected<E> &&geterr() && {
826 return std::move(this->m_unexpect);
828 constexpr
const unexpected<E> &&geterr() const && {
829 return std::move(this->m_unexpect);
832 constexpr
void destroy_val() {
get().~T(); }
838 struct expected_operations_base<void, E> : expected_storage_base<void, E> {
839 using expected_storage_base<void, E>::expected_storage_base;
841 template <
class... Args>
void construct() noexcept { this->m_has_val =
true; }
845 template <
class Rhs>
void construct_with(Rhs &&) noexcept {
846 this->m_has_val =
true;
849 template <
class... Args>
void construct_error(Args &&...args) noexcept {
850 new (std::addressof(this->m_unexpect))
851 unexpected<E>(std::forward<Args>(args)...);
852 this->m_has_val =
false;
855 template <
class Rhs>
void assign(Rhs &&rhs) noexcept {
856 if (!this->m_has_val) {
858 geterr().~unexpected<E>();
861 geterr() = std::forward<Rhs>(rhs).geterr();
864 if (!rhs.m_has_val) {
865 construct_error(std::forward<Rhs>(rhs).geterr());
870 bool has_value()
const {
return this->m_has_val; }
872 constexpr unexpected<E> &geterr() & {
873 return this->m_unexpect;
875 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
876 constexpr unexpected<E> &&geterr() && {
877 return std::move(this->m_unexpect);
879 constexpr
const unexpected<E> &&geterr() const && {
880 return std::move(this->m_unexpect);
883 constexpr
void destroy_val() {
890 template <
class T,
class E,
891 bool = is_void_or<T, GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
892 value &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
893 struct expected_copy_base : expected_operations_base<T, E> {
894 using expected_operations_base<T, E>::expected_operations_base;
898 template <
class T,
class E>
899 struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
900 using expected_operations_base<T, E>::expected_operations_base;
902 expected_copy_base() =
default;
903 expected_copy_base(
const expected_copy_base &rhs)
904 : expected_operations_base<T, E>(no_init) {
905 if (rhs.has_value()) {
906 this->construct_with(rhs);
908 this->construct_error(rhs.geterr());
912 expected_copy_base(expected_copy_base &&rhs) =
default;
913 expected_copy_base &operator=(
const expected_copy_base &rhs) =
default;
914 expected_copy_base &operator=(expected_copy_base &&rhs) =
default;
918 template <
class T,
class E,
919 bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
920 &&std::is_trivially_move_constructible<E>::value>
921 struct expected_move_base : expected_copy_base<T, E> {
922 using expected_copy_base<T, E>::expected_copy_base;
925 template <
class T,
class E>
926 struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
927 using expected_copy_base<T, E>::expected_copy_base;
929 expected_move_base() =
default;
930 expected_move_base(
const expected_move_base &rhs) =
default;
932 expected_move_base(expected_move_base &&rhs) noexcept(
933 std::is_nothrow_move_constructible<T>::value)
934 : expected_copy_base<T, E>(no_init) {
935 if (rhs.has_value()) {
936 this->construct_with(std::move(rhs));
938 this->construct_error(std::move(rhs.geterr()));
941 expected_move_base &operator=(
const expected_move_base &rhs) =
default;
942 expected_move_base &operator=(expected_move_base &&rhs) =
default;
946 template <
class T,
class E,
948 T, conjunction<GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
949 GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
950 GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
951 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
952 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
953 &&GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
954 struct expected_copy_assign_base : expected_move_base<T, E> {
955 using expected_move_base<T, E>::expected_move_base;
958 template <
class T,
class E>
959 struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
960 using expected_move_base<T, E>::expected_move_base;
962 expected_copy_assign_base() =
default;
963 expected_copy_assign_base(
const expected_copy_assign_base &rhs) =
default;
965 expected_copy_assign_base(expected_copy_assign_base &&rhs) =
default;
966 expected_copy_assign_base &operator=(
const expected_copy_assign_base &rhs) {
970 expected_copy_assign_base &
971 operator=(expected_copy_assign_base &&rhs) =
default;
975 template <
class T,
class E,
977 is_void_or<T, conjunction<std::is_trivially_destructible<T>,
978 std::is_trivially_move_constructible<T>,
979 std::is_trivially_move_assignable<T>>>::
980 value &&std::is_trivially_destructible<E>::value
981 &&std::is_trivially_move_constructible<E>::value
982 &&std::is_trivially_move_assignable<E>::value>
983 struct expected_move_assign_base : expected_copy_assign_base<T, E> {
984 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
987 template <
class T,
class E>
988 struct expected_move_assign_base<T, E, false>
989 : expected_copy_assign_base<T, E> {
990 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
992 expected_move_assign_base() =
default;
993 expected_move_assign_base(
const expected_move_assign_base &rhs) =
default;
995 expected_move_assign_base(expected_move_assign_base &&rhs) =
default;
997 expected_move_assign_base &
998 operator=(
const expected_move_assign_base &rhs) =
default;
1000 expected_move_assign_base &
1001 operator=(expected_move_assign_base &&rhs) noexcept(
1002 std::is_nothrow_move_constructible<T>::value
1003 &&std::is_nothrow_move_assignable<T>::value) {
1004 this->assign(std::move(rhs));
1011 template <
class T,
class E,
1012 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1013 std::is_copy_constructible<E>::value),
1014 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1015 std::is_move_constructible<E>::value)>
1016 struct expected_delete_ctor_base {
1017 expected_delete_ctor_base() =
default;
1018 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
1019 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1020 expected_delete_ctor_base &
1021 operator=(const expected_delete_ctor_base &) = default;
1022 expected_delete_ctor_base &
1023 operator=(expected_delete_ctor_base &&) noexcept = default;
1026 template <class T, class E>
1027 struct expected_delete_ctor_base<T, E, true, false> {
1028 expected_delete_ctor_base() =
default;
1029 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
1030 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1031 expected_delete_ctor_base &
1032 operator=(const expected_delete_ctor_base &) = default;
1033 expected_delete_ctor_base &
1034 operator=(expected_delete_ctor_base &&) noexcept = default;
1037 template <class T, class E>
1038 struct expected_delete_ctor_base<T, E, false, true> {
1039 expected_delete_ctor_base() =
default;
1040 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1041 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1042 expected_delete_ctor_base &
1043 operator=(const expected_delete_ctor_base &) = default;
1044 expected_delete_ctor_base &
1045 operator=(expected_delete_ctor_base &&) noexcept = default;
1048 template <class T, class E>
1049 struct expected_delete_ctor_base<T, E, false, false> {
1050 expected_delete_ctor_base() =
default;
1051 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1052 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1053 expected_delete_ctor_base &
1054 operator=(const expected_delete_ctor_base &) = default;
1055 expected_delete_ctor_base &
1056 operator=(expected_delete_ctor_base &&) noexcept = default;
1062 template <class T, class E,
1063 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1064 std::is_copy_constructible<E>::value &&
1065 is_copy_assignable_or_void<T>::value &&
1066 std::is_copy_assignable<E>::value),
1067 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1068 std::is_move_constructible<E>::value &&
1069 is_move_assignable_or_void<T>::value &&
1070 std::is_move_assignable<E>::value)>
1071 struct expected_delete_assign_base {
1072 expected_delete_assign_base() =
default;
1073 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1074 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1076 expected_delete_assign_base &
1077 operator=(const expected_delete_assign_base &) = default;
1078 expected_delete_assign_base &
1079 operator=(expected_delete_assign_base &&) noexcept = default;
1082 template <class T, class E>
1083 struct expected_delete_assign_base<T, E, true, false> {
1084 expected_delete_assign_base() =
default;
1085 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1086 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1088 expected_delete_assign_base &
1089 operator=(const expected_delete_assign_base &) = default;
1090 expected_delete_assign_base &
1091 operator=(expected_delete_assign_base &&) noexcept = delete;
1094 template <class T, class E>
1095 struct expected_delete_assign_base<T, E, false, true> {
1096 expected_delete_assign_base() =
default;
1097 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1098 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1100 expected_delete_assign_base &
1101 operator=(const expected_delete_assign_base &) = delete;
1102 expected_delete_assign_base &
1103 operator=(expected_delete_assign_base &&) noexcept = default;
1106 template <class T, class E>
1107 struct expected_delete_assign_base<T, E, false, false> {
1108 expected_delete_assign_base() =
default;
1109 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1110 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1112 expected_delete_assign_base &
1113 operator=(const expected_delete_assign_base &) = delete;
1114 expected_delete_assign_base &
1115 operator=(expected_delete_assign_base &&) noexcept = delete;
1120 struct default_constructor_tag {
1121 explicit constexpr default_constructor_tag() =
default;
1127 template <
class T,
class E,
1129 std::is_default_constructible<T>::value || std::is_void<T>::value>
1130 struct expected_default_ctor_base {
1131 constexpr expected_default_ctor_base() noexcept = default;
1132 constexpr expected_default_ctor_base(
1133 expected_default_ctor_base const &) noexcept = default;
1134 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1136 expected_default_ctor_base &
1137 operator=(expected_default_ctor_base const &) noexcept = default;
1138 expected_default_ctor_base &
1139 operator=(expected_default_ctor_base &&) noexcept = default;
1141 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1145 template <
class T,
class E>
struct expected_default_ctor_base<T, E, false> {
1146 constexpr expected_default_ctor_base() noexcept = delete;
1147 constexpr expected_default_ctor_base(
1148 expected_default_ctor_base const &) noexcept = default;
1149 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1151 expected_default_ctor_base &
1152 operator=(expected_default_ctor_base const &) noexcept = default;
1153 expected_default_ctor_base &
1154 operator=(expected_default_ctor_base &&) noexcept = default;
1156 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1160 template <
typename E>
1161 class bad_expected_access;
1163 template <>
class bad_expected_access<void> :
public std::exception
1166 virtual const char *what() const noexcept
override {
1167 return "Bad expected access";
1171 bad_expected_access() noexcept {}
1172 bad_expected_access(
const bad_expected_access&) =
default;
1173 bad_expected_access(bad_expected_access&&) =
default;
1174 bad_expected_access& operator=(
const bad_expected_access&) =
default;
1175 bad_expected_access& operator=(bad_expected_access&&) =
default;
1176 ~bad_expected_access() =
default;
1180 class bad_expected_access :
public bad_expected_access<void>
1183 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1185 const E &error() const & {
return m_val; }
1186 E &error() & {
return m_val; }
1187 const E &&error() const && {
return std::move(m_val); }
1188 E &&error() && {
return std::move(m_val); }
1194 template <
class T,
class E>
1195 class expected :
private detail::expected_move_assign_base<T, E>,
1196 private detail::expected_delete_ctor_base<T, E>,
1197 private detail::expected_delete_assign_base<T, E>,
1198 private detail::expected_default_ctor_base<T, E> {
1199 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1200 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1201 "T must not be in_place_t");
1202 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1203 "T must not be unexpect_t");
1205 !std::is_same<T,
typename std::remove_cv<unexpected<E>>::type>::value,
1206 "T must not be unexpected<E>");
1207 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1209 T *valptr() {
return std::addressof(this->m_val); }
1210 const T *valptr()
const {
return std::addressof(this->m_val); }
1211 unexpected<E> *errptr() {
return std::addressof(this->m_unexpect); }
1212 const unexpected<E> *errptr()
const {
1213 return std::addressof(this->m_unexpect);
1216 template <
class U = T,
1217 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1218 constexpr U &val() {
1221 constexpr unexpected<E> &err() {
return this->m_unexpect; }
1223 template <
class U = T,
1224 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1225 constexpr
const U &val()
const {
1228 constexpr
const unexpected<E> &err()
const {
return this->m_unexpect; }
1230 using impl_base = detail::expected_move_assign_base<T, E>;
1231 using ctor_base = detail::expected_default_ctor_base<T, E>;
1234 typedef T value_type;
1235 typedef E error_type;
1236 typedef unexpected<E> unexpected_type;
1238 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1240 template <
class F> constexpr
auto and_then(F &&f) & {
1241 return and_then_impl(*
this, std::forward<F>(f));
1243 template <
class F> constexpr
auto and_then(F &&f) && {
1244 return and_then_impl(std::move(*
this), std::forward<F>(f));
1246 template <
class F> constexpr
auto and_then(F &&f)
const & {
1247 return and_then_impl(*
this, std::forward<F>(f));
1249 template <
class F> constexpr
auto and_then(F &&f)
const && {
1250 return and_then_impl(std::move(*
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(*
this, std::forward<F>(f));
1263 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1264 std::forward<F>(f))) {
1265 return and_then_impl(std::move(*
this), std::forward<F>(f));
1268 constexpr
auto and_then(F &&f)
const & -> decltype(and_then_impl(
1269 std::declval<expected const &>(), std::forward<F>(f))) {
1270 return and_then_impl(*
this, std::forward<F>(f));
1273 constexpr
auto and_then(F &&f)
const && -> decltype(and_then_impl(
1274 std::declval<expected const &&>(), std::forward<F>(f))) {
1275 return and_then_impl(std::move(*
this), std::forward<F>(f));
1280 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1281 template <
class F> constexpr
auto map(F &&f) & {
1282 return expected_map_impl(*
this, std::forward<F>(f));
1284 template <
class F> constexpr
auto map(F &&f) && {
1285 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1287 template <
class F> constexpr
auto map(F &&f)
const & {
1288 return expected_map_impl(*
this, std::forward<F>(f));
1290 template <
class F> constexpr
auto map(F &&f)
const && {
1291 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1295 constexpr decltype(expected_map_impl(
1296 std::declval<expected &>(), std::declval<F &&>()))
1298 return expected_map_impl(*
this, std::forward<F>(f));
1301 constexpr decltype(expected_map_impl(std::declval<expected>(),
1302 std::declval<F &&>()))
1304 return expected_map_impl(std::move(*
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(*
this, std::forward<F>(f));
1313 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1314 std::declval<F &&>()))
1315 map(F &&f) const && {
1316 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1320 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1321 template <
class F> constexpr
auto transform(F &&f) & {
1322 return expected_map_impl(*
this, std::forward<F>(f));
1324 template <
class F> constexpr
auto transform(F &&f) && {
1325 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1327 template <
class F> constexpr
auto transform(F &&f)
const & {
1328 return expected_map_impl(*
this, std::forward<F>(f));
1330 template <
class F> constexpr
auto transform(F &&f)
const && {
1331 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1335 constexpr decltype(expected_map_impl(
1336 std::declval<expected &>(), std::declval<F &&>()))
1337 transform(F &&f) & {
1338 return expected_map_impl(*
this, std::forward<F>(f));
1341 constexpr decltype(expected_map_impl(std::declval<expected>(),
1342 std::declval<F &&>()))
1343 transform(F &&f) && {
1344 return expected_map_impl(std::move(*
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(*
this, std::forward<F>(f));
1353 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1354 std::declval<F &&>()))
1355 transform(F &&f) const && {
1356 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1360 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1361 template <
class F> constexpr
auto map_error(F &&f) & {
1362 return map_error_impl(*
this, std::forward<F>(f));
1364 template <
class F> constexpr
auto map_error(F &&f) && {
1365 return map_error_impl(std::move(*
this), std::forward<F>(f));
1367 template <
class F> constexpr
auto map_error(F &&f)
const & {
1368 return map_error_impl(*
this, std::forward<F>(f));
1370 template <
class F> constexpr
auto map_error(F &&f)
const && {
1371 return map_error_impl(std::move(*
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(*
this, std::forward<F>(f));
1381 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1382 std::declval<F &&>()))
1383 map_error(F &&f) && {
1384 return map_error_impl(std::move(*
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(*
this, std::forward<F>(f));
1393 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1394 std::declval<F &&>()))
1395 map_error(F &&f) const && {
1396 return map_error_impl(std::move(*
this), std::forward<F>(f));
1399 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1400 template <
class F> constexpr
auto transform_error(F &&f) & {
1401 return map_error_impl(*
this, std::forward<F>(f));
1403 template <
class F> constexpr
auto transform_error(F &&f) && {
1404 return map_error_impl(std::move(*
this), std::forward<F>(f));
1406 template <
class F> constexpr
auto transform_error(F &&f)
const & {
1407 return map_error_impl(*
this, std::forward<F>(f));
1409 template <
class F> constexpr
auto transform_error(F &&f)
const && {
1410 return map_error_impl(std::move(*
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(*
this, std::forward<F>(f));
1420 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1421 std::declval<F &&>()))
1422 transform_error(F &&f) && {
1423 return map_error_impl(std::move(*
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(*
this, std::forward<F>(f));
1432 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1433 std::declval<F &&>()))
1434 transform_error(F &&f) const && {
1435 return map_error_impl(std::move(*
this), std::forward<F>(f));
1438 template <
class F> expected constexpr or_else(F &&f) & {
1439 return or_else_impl(*
this, std::forward<F>(f));
1442 template <
class F> expected constexpr or_else(F &&f) && {
1443 return or_else_impl(std::move(*
this), std::forward<F>(f));
1446 template <
class F> expected constexpr or_else(F &&f)
const & {
1447 return or_else_impl(*
this, std::forward<F>(f));
1450 template <
class F> expected constexpr or_else(F &&f)
const && {
1451 return or_else_impl(std::move(*
this), std::forward<F>(f));
1454 constexpr expected() =
default;
1455 constexpr expected(
const expected &rhs) =
default;
1456 constexpr expected(expected &&rhs) =
default;
1457 expected &operator=(
const expected &rhs) =
default;
1458 expected &operator=(expected &&rhs) =
default;
1460 template <
class... Args,
1461 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1463 constexpr expected(in_place_t, Args &&...args)
1464 : impl_base(in_place, std::forward<Args>(args)...),
1465 ctor_base(detail::default_constructor_tag{}) {}
1467 template <
class U,
class... Args,
1468 detail::enable_if_t<std::is_constructible<
1469 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1470 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1471 : impl_base(in_place, il, std::forward<Args>(args)...),
1472 ctor_base(detail::default_constructor_tag{}) {}
1474 template <
class G = E,
1475 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1477 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1479 explicit constexpr expected(
const unexpected<G> &e)
1480 : impl_base(unexpect, e.value()),
1481 ctor_base(detail::default_constructor_tag{}) {}
1485 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1487 detail::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1488 constexpr expected(unexpected<G>
const &e)
1489 : impl_base(unexpect, e.value()),
1490 ctor_base(detail::default_constructor_tag{}) {}
1494 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1495 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1496 explicit constexpr expected(unexpected<G> &&e) noexcept(
1497 std::is_nothrow_constructible<E, G &&>::value)
1498 : impl_base(unexpect, std::move(e.value())),
1499 ctor_base(detail::default_constructor_tag{}) {}
1503 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1504 detail::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1505 constexpr expected(unexpected<G> &&e) noexcept(
1506 std::is_nothrow_constructible<E, G &&>::value)
1507 : impl_base(unexpect, std::move(e.value())),
1508 ctor_base(detail::default_constructor_tag{}) {}
1510 template <
class... Args,
1511 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1513 constexpr
explicit expected(unexpect_t, Args &&...args)
1514 : impl_base(unexpect, std::forward<Args>(args)...),
1515 ctor_base(detail::default_constructor_tag{}) {}
1517 template <
class U,
class... Args,
1518 detail::enable_if_t<std::is_constructible<
1519 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1520 constexpr
explicit expected(unexpect_t, std::initializer_list<U> il,
1522 : impl_base(unexpect, il, std::forward<Args>(args)...),
1523 ctor_base(detail::default_constructor_tag{}) {}
1525 template <
class U,
class G,
1526 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1527 std::is_convertible<G const &, E>::value)> * =
1529 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1531 explicit constexpr expected(
const expected<U, G> &rhs)
1532 : ctor_base(detail::default_constructor_tag{}) {
1533 if (rhs.has_value()) {
1534 this->construct(*rhs);
1536 this->construct_error(rhs.error());
1540 template <
class U,
class G,
1541 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1542 std::is_convertible<G const &, E>::value)> * =
1544 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1546 constexpr expected(
const expected<U, G> &rhs)
1547 : ctor_base(detail::default_constructor_tag{}) {
1548 if (rhs.has_value()) {
1549 this->construct(*rhs);
1551 this->construct_error(rhs.error());
1557 detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1558 std::is_convertible<G &&, E>::value)> * =
nullptr,
1559 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1560 explicit constexpr expected(expected<U, G> &&rhs)
1561 : ctor_base(detail::default_constructor_tag{}) {
1562 if (rhs.has_value()) {
1563 this->construct(std::move(*rhs));
1565 this->construct_error(std::move(rhs.error()));
1571 detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1572 std::is_convertible<G &&, E>::value)> * =
nullptr,
1573 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1574 constexpr expected(expected<U, G> &&rhs)
1575 : ctor_base(detail::default_constructor_tag{}) {
1576 if (rhs.has_value()) {
1577 this->construct(std::move(*rhs));
1579 this->construct_error(std::move(rhs.error()));
1585 detail::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1586 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1587 explicit constexpr expected(U &&v)
1588 : expected(in_place, std::forward<U>(v)) {}
1592 detail::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1593 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1594 constexpr expected(U &&v)
1595 : expected(in_place, std::forward<U>(v)) {}
1598 class U = T,
class G = T,
1599 detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1601 detail::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1602 detail::enable_if_t<
1603 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1604 !detail::conjunction<std::is_scalar<T>,
1605 std::is_same<T, detail::decay_t<U>>>::value &&
1606 std::is_constructible<T, U>::value &&
1607 std::is_assignable<G &, U>::value &&
1608 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1609 expected &
operator=(U &&v) {
1611 val() = std::forward<U>(v);
1613 err().~unexpected<E>();
1614 ::new (valptr()) T(std::forward<U>(v));
1615 this->m_has_val = true;
1622 class U = T, class G = T,
1623 detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
1625 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr,
1626 detail::enable_if_t<
1627 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1628 !detail::conjunction<std::is_scalar<T>,
1629 std::is_same<T, detail::decay_t<U>>>::value &&
1630 std::is_constructible<T, U>::value &&
1631 std::is_assignable<G &, U>::value &&
1632 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1633 expected &operator=(U &&v) {
1635 val() = std::forward<U>(v);
1637 auto tmp = std::move(err());
1638 err().~unexpected<E>();
1640 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1642 ::new (valptr()) T(std::forward<U>(v));
1643 this->m_has_val = true;
1645 err() = std::move(tmp);
1649 ::new (valptr()) T(std::forward<U>(v));
1650 this->m_has_val = true;
1657 template <
class G = E,
1658 detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1659 std::is_assignable<G &, G>::value> * =
nullptr>
1660 expected &operator=(
const unexpected<G> &rhs) {
1664 this->destroy_val();
1665 ::new (errptr()) unexpected<E>(rhs);
1666 this->m_has_val = false;
1672 template <class G = E,
1673 detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1674 std::is_move_assignable<G>::value> * =
nullptr>
1675 expected &operator=(unexpected<G> &&rhs) noexcept {
1677 err() = std::move(rhs);
1679 this->destroy_val();
1680 ::new (errptr()) unexpected<E>(std::move(rhs));
1681 this->m_has_val = false;
1687 template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1688 T, Args &&...>::value> * =
nullptr>
1689 void emplace(Args &&...args) {
1693 err().~unexpected<E>();
1694 this->m_has_val =
true;
1696 ::new (valptr()) T(std::forward<Args>(args)...);
1699 template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1700 T, Args &&...>::value> * =
nullptr>
1701 void emplace(Args &&...args) {
1704 ::new (valptr()) T(std::forward<Args>(args)...);
1706 auto tmp = std::move(err());
1707 err().~unexpected<E>();
1709 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1711 ::new (valptr()) T(std::forward<Args>(args)...);
1712 this->m_has_val = true;
1714 err() = std::move(tmp);
1718 ::new (valptr()) T(std::forward<Args>(args)...);
1719 this->m_has_val = true;
1724 template <
class U,
class... Args,
1725 detail::enable_if_t<std::is_nothrow_constructible<
1726 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1727 void emplace(std::initializer_list<U> il, Args &&...args) {
1729 T t(il, std::forward<Args>(args)...);
1730 val() = std::move(t);
1732 err().~unexpected<E>();
1733 ::new (valptr()) T(il, std::forward<Args>(args)...);
1734 this->m_has_val = true;
1738 template <class U, class... Args,
1739 detail::enable_if_t<!std::is_nothrow_constructible<
1740 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1741 void emplace(std::initializer_list<U> il, Args &&...args) {
1743 T t(il, std::forward<Args>(args)...);
1744 val() = std::move(t);
1746 auto tmp = std::move(err());
1747 err().~unexpected<E>();
1749 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1751 ::new (valptr()) T(il, std::forward<Args>(args)...);
1752 this->m_has_val = true;
1754 err() = std::move(tmp);
1758 ::new (valptr()) T(il, std::forward<Args>(args)...);
1759 this->m_has_val = true;
1765 using t_is_void = std::true_type;
1766 using t_is_not_void = std::false_type;
1767 using t_is_nothrow_move_constructible = std::true_type;
1768 using move_constructing_t_can_throw = std::false_type;
1769 using e_is_nothrow_move_constructible = std::true_type;
1770 using move_constructing_e_can_throw = std::false_type;
1772 void swap_where_both_have_value(expected & , t_is_void) noexcept {
1776 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1778 swap(val(), rhs.val());
1781 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1782 std::is_nothrow_move_constructible<E>::value) {
1783 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1784 rhs.err().~unexpected_type();
1785 std::
swap(this->m_has_val, rhs.m_has_val);
1788 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1789 swap_where_only_one_has_value_and_t_is_not_void(
1790 rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1791 typename std::is_nothrow_move_constructible<E>::type{});
1794 void swap_where_only_one_has_value_and_t_is_not_void(
1795 expected &rhs, t_is_nothrow_move_constructible,
1796 e_is_nothrow_move_constructible) noexcept {
1797 auto temp = std::move(val());
1799 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1800 rhs.err().~unexpected_type();
1801 ::new (rhs.valptr()) T(std::move(temp));
1802 std::
swap(this->m_has_val, rhs.m_has_val);
1805 void swap_where_only_one_has_value_and_t_is_not_void(
1806 expected &rhs, t_is_nothrow_move_constructible,
1807 move_constructing_e_can_throw) {
1808 auto temp = std::move(val());
1810 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1812 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1813 rhs.err().~unexpected_type();
1814 ::new (rhs.valptr()) T(std::move(temp));
1815 std::
swap(this->m_has_val, rhs.m_has_val);
1817 val() = std::move(temp);
1821 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1822 rhs.err().~unexpected_type();
1823 ::new (rhs.valptr()) T(std::move(temp));
1824 std::
swap(this->m_has_val, rhs.m_has_val);
1828 void swap_where_only_one_has_value_and_t_is_not_void(
1829 expected &rhs, move_constructing_t_can_throw,
1830 e_is_nothrow_move_constructible) {
1831 auto temp = std::move(rhs.err());
1832 rhs.err().~unexpected_type();
1833 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1835 ::new (rhs.valptr()) T(std::move(val()));
1837 ::new (errptr()) unexpected_type(std::move(temp));
1838 std::
swap(this->m_has_val, rhs.m_has_val);
1840 rhs.err() = std::move(temp);
1844 ::new (rhs.valptr()) T(std::move(val()));
1846 ::new (errptr()) unexpected_type(std::move(temp));
1847 std::
swap(this->m_has_val, rhs.m_has_val);
1852 template <
class OT = T,
class OE = E>
1853 detail::enable_if_t<detail::is_swappable<OT>::value &&
1854 detail::is_swappable<OE>::value &&
1855 (std::is_nothrow_move_constructible<OT>::value ||
1856 std::is_nothrow_move_constructible<OE>::value)>
1857 swap(expected &rhs) noexcept(
1858 std::is_nothrow_move_constructible<T>::value
1859 &&detail::is_nothrow_swappable<T>::value
1860 &&std::is_nothrow_move_constructible<E>::value
1861 &&detail::is_nothrow_swappable<E>::value) {
1862 if (has_value() && rhs.has_value()) {
1863 swap_where_both_have_value(rhs,
typename std::is_void<T>::type{});
1864 }
else if (!has_value() && rhs.has_value()) {
1866 }
else if (has_value()) {
1867 swap_where_only_one_has_value(rhs,
typename std::is_void<T>::type{});
1870 swap(err(), rhs.err());
1874 constexpr
const T *operator->()
const {
1875 assert(has_value());
1878 constexpr T *operator->() {
1879 assert(has_value());
1883 template <
class U = T,
1884 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1885 constexpr
const U &operator*() const & {
1886 assert(has_value());
1889 template <
class U = T,
1890 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1891 constexpr U &operator*() & {
1892 assert(has_value());
1895 template <
class U = T,
1896 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1897 constexpr
const U &&operator*() const && {
1898 assert(has_value());
1899 return std::move(val());
1901 template <
class U = T,
1902 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1903 constexpr U &&operator*() && {
1904 assert(has_value());
1905 return std::move(val());
1908 constexpr
bool has_value() const noexcept {
return this->m_has_val; }
1909 constexpr
explicit operator bool() const noexcept {
return this->m_has_val; }
1911 template <
class U = T,
1912 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1913 constexpr
const U &value() const & {
1915 detail::throw_exception(bad_expected_access<E>(err().value()));
1918 template <
class U = T,
1919 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1920 constexpr U &value() & {
1922 detail::throw_exception(bad_expected_access<E>(err().value()));
1925 template <
class U = T,
1926 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1927 constexpr
const U &&value() const && {
1929 detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1930 return std::move(val());
1932 template <
class U = T,
1933 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1934 constexpr U &&value() && {
1936 detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1937 return std::move(val());
1940 constexpr
const E &error() const & {
1941 assert(!has_value());
1942 return err().value();
1944 constexpr E &error() & {
1945 assert(!has_value());
1946 return err().value();
1948 constexpr
const E &&error() const && {
1949 assert(!has_value());
1950 return std::move(err().value());
1952 constexpr E &&error() && {
1953 assert(!has_value());
1954 return std::move(err().value());
1957 template <
class U> constexpr T value_or(U &&v)
const & {
1958 static_assert(std::is_copy_constructible<T>::value &&
1959 std::is_convertible<U &&, T>::value,
1960 "T must be copy-constructible and convertible to from U&&");
1961 return bool(*
this) ? **this :
static_cast<T
>(std::forward<U>(v));
1963 template <
class U> constexpr T value_or(U &&v) && {
1964 static_assert(std::is_move_constructible<T>::value &&
1965 std::is_convertible<U &&, T>::value,
1966 "T must be move-constructible and convertible to from U&&");
1967 return bool(*
this) ? std::move(**
this) : static_cast<T>(std::forward<U>(v));
1972 template <
class Exp>
using exp_t =
typename detail::decay_t<Exp>::value_type;
1973 template <
class Exp>
using err_t =
typename detail::decay_t<Exp>::error_type;
1974 template <
class Exp,
class Ret>
using ret_t = expected<Ret, err_t<Exp>>;
1976 template <
class Exp,
class F,
1977 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1978 class Ret = decltype(detail::invoke(std::declval<F>(),
1979 *std::declval<Exp>()))>
1980 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1981 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1983 return exp.has_value()
1984 ? detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp))
1985 : Ret(unexpect, std::forward<Exp>(exp).error());
1988 template <
class Exp,
class F,
1989 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
1990 class Ret = decltype(detail::invoke(std::declval<F>()))>
1991 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1992 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1994 return exp.has_value() ? detail::invoke(std::forward<F>(f))
1995 : Ret(unexpect, std::forward<Exp>(exp).error());
1998 template <
class Exp,
class F,
1999 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2000 class Ret = decltype(detail::invoke(std::declval<F>(),
2001 *std::declval<Exp>())),
2002 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2003 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
2004 using result = ret_t<Exp, detail::decay_t<Ret>>;
2005 return exp.has_value() ? result(detail::invoke(std::forward<F>(f),
2006 *std::forward<Exp>(exp)))
2007 : result(unexpect, std::forward<Exp>(exp).error());
2010 template <
class Exp,
class F,
2011 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2012 class Ret = decltype(detail::invoke(std::declval<F>(),
2013 *std::declval<Exp>())),
2014 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2015 auto expected_map_impl(Exp &&exp, F &&f) {
2016 using result = expected<void, err_t<Exp>>;
2017 if (exp.has_value()) {
2018 detail::invoke(std::forward<F>(f), *std::forward<Exp>(exp));
2022 return result(unexpect, std::forward<Exp>(exp).error());
2025 template <
class Exp,
class F,
2026 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2027 class Ret = decltype(detail::invoke(std::declval<F>())),
2028 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2029 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
2030 using result = ret_t<Exp, detail::decay_t<Ret>>;
2031 return exp.has_value() ? result(detail::invoke(std::forward<F>(f)))
2032 : result(unexpect, std::forward<Exp>(exp).error());
2035 template <
class Exp,
class F,
2036 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2037 class Ret = decltype(detail::invoke(std::declval<F>())),
2038 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2039 auto expected_map_impl(Exp &&exp, F &&f) {
2040 using result = expected<void, err_t<Exp>>;
2041 if (exp.has_value()) {
2042 detail::invoke(std::forward<F>(f));
2046 return result(unexpect, std::forward<Exp>(exp).error());
2049 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
2050 template <
class Exp,
class F,
2051 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2052 class Ret = decltype(detail::invoke(std::declval<F>(),
2053 std::declval<Exp>().error())),
2054 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2055 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2056 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2057 return exp.has_value()
2058 ? result(*std::forward<Exp>(exp))
2059 : result(unexpect, detail::invoke(std::forward<F>(f),
2060 std::forward<Exp>(exp).error()));
2062 template <
class Exp,
class F,
2063 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2064 class Ret = decltype(detail::invoke(std::declval<F>(),
2065 std::declval<Exp>().error())),
2066 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2067 auto map_error_impl(Exp &&exp, F &&f) {
2068 using result = expected<exp_t<Exp>, monostate>;
2069 if (exp.has_value()) {
2070 return result(*std::forward<Exp>(exp));
2073 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2074 return result(unexpect, monostate{});
2076 template <
class Exp,
class F,
2077 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2078 class Ret = decltype(detail::invoke(std::declval<F>(),
2079 std::declval<Exp>().error())),
2080 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2081 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2082 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2083 return exp.has_value()
2085 : result(unexpect, detail::invoke(std::forward<F>(f),
2086 std::forward<Exp>(exp).error()));
2088 template <
class Exp,
class F,
2089 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2090 class Ret = decltype(detail::invoke(std::declval<F>(),
2091 std::declval<Exp>().error())),
2092 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2093 auto map_error_impl(Exp &&exp, F &&f) {
2094 using result = expected<exp_t<Exp>, monostate>;
2095 if (exp.has_value()) {
2099 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2100 return result(unexpect, monostate{});
2103 template <
class Exp,
class F,
2104 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2105 class Ret = decltype(detail::invoke(std::declval<F>(),
2106 std::declval<Exp>().error())),
2107 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2108 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2109 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2110 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2112 return exp.has_value()
2113 ? result(*std::forward<Exp>(exp))
2114 : result(unexpect, detail::invoke(std::forward<F>(f),
2115 std::forward<Exp>(exp).error()));
2118 template <
class Exp,
class F,
2119 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2120 class Ret = decltype(detail::invoke(std::declval<F>(),
2121 std::declval<Exp>().error())),
2122 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2123 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2124 using result = expected<exp_t<Exp>, monostate>;
2125 if (exp.has_value()) {
2126 return result(*std::forward<Exp>(exp));
2129 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2130 return result(unexpect, monostate{});
2133 template <
class Exp,
class F,
2134 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2135 class Ret = decltype(detail::invoke(std::declval<F>(),
2136 std::declval<Exp>().error())),
2137 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2138 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2139 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2140 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2142 return exp.has_value()
2144 : result(unexpect, detail::invoke(std::forward<F>(f),
2145 std::forward<Exp>(exp).error()));
2148 template <
class Exp,
class F,
2149 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2150 class Ret = decltype(detail::invoke(std::declval<F>(),
2151 std::declval<Exp>().error())),
2152 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2153 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2154 using result = expected<exp_t<Exp>, monostate>;
2155 if (exp.has_value()) {
2159 detail::invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2160 return result(unexpect, monostate{});
2164 template <
class Exp,
class F,
2165 class Ret = decltype(detail::invoke(std::declval<F>(),
2166 std::declval<Exp>().error())),
2167 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2168 constexpr
auto or_else_impl(Exp &&exp, F &&f) {
2169 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2170 return exp.has_value() ? std::forward<Exp>(exp)
2171 : detail::invoke(std::forward<F>(f),
2172 std::forward<Exp>(exp).error());
2175 template <
class Exp,
class F,
2176 class Ret = decltype(detail::invoke(std::declval<F>(),
2177 std::declval<Exp>().error())),
2178 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2179 detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2180 return exp.has_value() ? std::forward<Exp>(exp)
2181 : (detail::invoke(std::forward<F>(f),
2182 std::forward<Exp>(exp).error()),
2183 std::forward<Exp>(exp));
2188 template <
class T,
class E,
class U,
class F>
2189 constexpr
bool operator==(
const expected<T, E> &lhs,
2190 const expected<U, F> &rhs) {
2191 return (lhs.has_value() != rhs.has_value())
2193 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2195 template <
class T,
class E,
class U,
class F>
2196 constexpr
bool operator!=(
const expected<T, E> &lhs,
2197 const expected<U, F> &rhs) {
2198 return (lhs.has_value() != rhs.has_value())
2200 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2202 template <
class E,
class F>
2203 constexpr
bool operator==(
const expected<void, E> &lhs,
2204 const expected<void, F> &rhs) {
2205 return (lhs.has_value() != rhs.has_value())
2207 : (!lhs.has_value() ? lhs.error() == rhs.error() :
true);
2209 template <
class E,
class F>
2210 constexpr
bool operator!=(
const expected<void, E> &lhs,
2211 const expected<void, F> &rhs) {
2212 return (lhs.has_value() != rhs.has_value())
2214 : (!lhs.has_value() ? lhs.error() == rhs.error() :
false);
2217 template <
class T,
class E,
class U>
2218 constexpr
bool operator==(
const expected<T, E> &x,
const U &v) {
2219 return x.has_value() ? *x == v :
false;
2221 template <
class T,
class E,
class U>
2222 constexpr
bool operator==(
const U &v,
const expected<T, E> &x) {
2223 return x.has_value() ? *x == v :
false;
2225 template <
class T,
class E,
class U>
2226 constexpr
bool operator!=(
const expected<T, E> &x,
const U &v) {
2227 return x.has_value() ? *x != v :
true;
2229 template <
class T,
class E,
class U>
2230 constexpr
bool operator!=(
const U &v,
const expected<T, E> &x) {
2231 return x.has_value() ? *x != v :
true;
2234 template <
class T,
class E>
2235 constexpr
bool operator==(
const expected<T, E> &x,
const unexpected<E> &e) {
2236 return x.has_value() ? false : x.error() == e.value();
2238 template <
class T,
class E>
2239 constexpr
bool operator==(
const unexpected<E> &e,
const expected<T, E> &x) {
2240 return x.has_value() ? false : x.error() == e.value();
2242 template <
class T,
class E>
2243 constexpr
bool operator!=(
const expected<T, E> &x,
const unexpected<E> &e) {
2244 return x.has_value() ? true : x.error() != e.value();
2246 template <
class T,
class E>
2247 constexpr
bool operator!=(
const unexpected<E> &e,
const expected<T, E> &x) {
2248 return x.has_value() ? true : x.error() != e.value();
2251 template <
class T,
class E,
2252 detail::enable_if_t<(std::is_void<T>::value ||
2253 std::is_move_constructible<T>::value) &&
2254 detail::is_swappable<T>::value &&
2255 std::is_move_constructible<E>::value &&
2256 detail::is_swappable<E>::value> * =
nullptr>
2257 void swap(expected<T, E> &lhs,
2258 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: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
constexpr auto get(span< E, S > s) -> decltype(s[N])
Return a reference to the Nth element of a given span.
Definition: span.h:544
Namespace gul14 contains all functions and classes of the General Utility Library.
Definition: doxygen.h:26
Some metaprogramming traits for the General Utility Library.
Declaration of the in_place_t family of types and constants and of the monostate type.