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 {};
253 namespace swap_adl_tests {
257 template <
class T> tag
swap(T &, T &);
258 template <
class T, std::
size_t N> tag
swap(T (&a)[N], T (&b)[N]);
262 template <
class,
class> std::false_type can_swap(...) noexcept(false);
263 template <class T, class U,
264 class = decltype(
swap(std::declval<T &>(), std::declval<U &>()))>
265 std::true_type can_swap(
int) noexcept(noexcept(
swap(std::declval<T &>(),
266 std::declval<U &>())));
268 template <class, class> std::false_type uses_std(...);
269 template <class T, class U>
270 std::is_same<decltype(
swap(std::declval<T &>(), std::declval<U &>())), tag>
274 struct is_std_swap_noexcept
275 : std::integral_constant<
bool,
276 std::is_nothrow_move_constructible<T>::value &&
277 std::is_nothrow_move_assignable<T>::value> {};
279 template <
class T, std::
size_t N>
280 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> {};
282 template <
class T,
class U>
283 struct is_adl_swap_noexcept
284 : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> {};
287 template <
class T,
class U = T>
289 : std::integral_constant<
291 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value &&
292 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value ||
293 (std::is_move_assignable<T>::value &&
294 std::is_move_constructible<T>::value))> {};
296 template <
class T, std::
size_t N>
297 struct is_swappable<T[N], T[N]>
298 : std::integral_constant<
300 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value &&
301 (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(
303 is_swappable<T, T>::value)> {};
305 template <
class T,
class U = T>
306 struct is_nothrow_swappable
307 : std::integral_constant<
309 is_swappable<T, U>::value &&
310 ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
311 detail::swap_adl_tests::is_std_swap_noexcept<T>::value) ||
312 (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value &&
313 detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> {};
317 template <
class T>
struct is_expected_impl : std::false_type {};
318 template <
class T,
class E>
319 struct is_expected_impl<expected<T, E>> : std::true_type {};
320 template <
class T>
using is_expected = is_expected_impl<decay_t<T>>;
322 template <
class T,
class E,
class U>
323 using expected_enable_forward_value = detail::enable_if_t<
324 std::is_constructible<T, U &&>::value &&
325 !std::is_same<detail::decay_t<U>, in_place_t>::value &&
326 !std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
327 !std::is_same<unexpected<E>, detail::decay_t<U>>::value>;
329 template <
class T,
class E,
class U,
class G,
class UR,
class GR>
330 using expected_enable_from_other = detail::enable_if_t<
331 std::is_constructible<T, UR>::value &&
332 std::is_constructible<E, GR>::value &&
333 !std::is_constructible<T, expected<U, G> &>::value &&
334 !std::is_constructible<T, expected<U, G> &&>::value &&
335 !std::is_constructible<T, const expected<U, G> &>::value &&
336 !std::is_constructible<T, const expected<U, G> &&>::value &&
337 !std::is_convertible<expected<U, G> &, T>::value &&
338 !std::is_convertible<expected<U, G> &&, T>::value &&
339 !std::is_convertible<const expected<U, G> &, T>::value &&
340 !std::is_convertible<const expected<U, G> &&, T>::value>;
342 template <
class T,
class U>
343 using is_void_or = conditional_t<std::is_void<T>::value, std::true_type, U>;
346 using is_copy_constructible_or_void =
347 is_void_or<T, std::is_copy_constructible<T>>;
350 using is_move_constructible_or_void =
351 is_void_or<T, std::is_move_constructible<T>>;
354 using is_copy_assignable_or_void = is_void_or<T, std::is_copy_assignable<T>>;
357 using is_move_assignable_or_void = is_void_or<T, std::is_move_assignable<T>>;
360 static constexpr no_init_t no_init{};
368 template <class T, class E, bool = std::is_trivially_destructible<T>::value,
369 bool = std::is_trivially_destructible<E>::value>
370 struct expected_storage_base {
371 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
372 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
374 template <
class... Args,
375 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
377 constexpr expected_storage_base(in_place_t, Args &&...args)
378 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
380 template <
class U,
class... Args,
381 detail::enable_if_t<std::is_constructible<
382 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
383 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
385 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
386 template <
class... Args,
387 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
389 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
390 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
392 template <
class U,
class... Args,
393 detail::enable_if_t<std::is_constructible<
394 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
395 constexpr
explicit expected_storage_base(unexpect_t,
396 std::initializer_list<U> il,
398 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
400 ~expected_storage_base() {
404 m_unexpect.~unexpected<E>();
409 unexpected<E> m_unexpect;
417 template <
class T,
class E>
struct expected_storage_base<T, E, true, true> {
418 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
419 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
421 template <
class... Args,
422 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
424 constexpr expected_storage_base(in_place_t, Args &&...args)
425 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
427 template <
class U,
class... Args,
428 detail::enable_if_t<std::is_constructible<
429 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
430 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
432 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
433 template <
class... Args,
434 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
436 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
437 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
439 template <
class U,
class... Args,
440 detail::enable_if_t<std::is_constructible<
441 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
442 constexpr
explicit expected_storage_base(unexpect_t,
443 std::initializer_list<U> il,
445 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
447 ~expected_storage_base() =
default;
450 unexpected<E> m_unexpect;
457 template <
class T,
class E>
struct expected_storage_base<T, E, true, false> {
458 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
459 constexpr expected_storage_base(no_init_t)
460 : m_no_init(), m_has_val(false) {}
462 template <
class... Args,
463 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
465 constexpr expected_storage_base(in_place_t, Args &&...args)
466 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
468 template <
class U,
class... Args,
469 detail::enable_if_t<std::is_constructible<
470 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
471 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
473 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
474 template <
class... Args,
475 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
477 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
478 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
480 template <
class U,
class... Args,
481 detail::enable_if_t<std::is_constructible<
482 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
483 constexpr
explicit expected_storage_base(unexpect_t,
484 std::initializer_list<U> il,
486 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
488 ~expected_storage_base() {
490 m_unexpect.~unexpected<E>();
496 unexpected<E> m_unexpect;
503 template <
class T,
class E>
struct expected_storage_base<T, E, false, true> {
504 constexpr expected_storage_base() : m_val(T{}), m_has_val(true) {}
505 constexpr expected_storage_base(no_init_t) : m_no_init(), m_has_val(false) {}
507 template <
class... Args,
508 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
510 constexpr expected_storage_base(in_place_t, Args &&...args)
511 : m_val(std::forward<Args>(args)...), m_has_val(true) {}
513 template <
class U,
class... Args,
514 detail::enable_if_t<std::is_constructible<
515 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
516 constexpr expected_storage_base(in_place_t, std::initializer_list<U> il,
518 : m_val(il, std::forward<Args>(args)...), m_has_val(true) {}
519 template <
class... Args,
520 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
522 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
523 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
525 template <
class U,
class... Args,
526 detail::enable_if_t<std::is_constructible<
527 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
528 constexpr
explicit expected_storage_base(unexpect_t,
529 std::initializer_list<U> il,
531 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
533 ~expected_storage_base() {
540 unexpected<E> m_unexpect;
547 template <
class E>
struct expected_storage_base<void, E, false, true> {
553 expected_storage_base() : m_has_val(true) {}
555 constexpr expected_storage_base(no_init_t) : m_val(), m_has_val(false) {}
557 constexpr expected_storage_base(in_place_t) : m_has_val(true) {}
559 template <
class... Args,
560 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
562 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
563 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
565 template <
class U,
class... Args,
566 detail::enable_if_t<std::is_constructible<
567 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
568 constexpr
explicit expected_storage_base(unexpect_t,
569 std::initializer_list<U> il,
571 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
573 ~expected_storage_base() =
default;
576 unexpected<E> m_unexpect;
583 template <
class E>
struct expected_storage_base<void, E, false, false> {
584 constexpr expected_storage_base() : m_dummy(), m_has_val(true) {}
585 constexpr expected_storage_base(no_init_t) : m_dummy(), m_has_val(false) {}
587 constexpr expected_storage_base(in_place_t) : m_dummy(), m_has_val(true) {}
589 template <
class... Args,
590 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
592 constexpr
explicit expected_storage_base(unexpect_t, Args &&...args)
593 : m_unexpect(std::forward<Args>(args)...), m_has_val(false) {}
595 template <
class U,
class... Args,
596 detail::enable_if_t<std::is_constructible<
597 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
598 constexpr
explicit expected_storage_base(unexpect_t,
599 std::initializer_list<U> il,
601 : m_unexpect(il, std::forward<Args>(args)...), m_has_val(false) {}
603 ~expected_storage_base() {
605 m_unexpect.~unexpected<E>();
610 unexpected<E> m_unexpect;
618 template <
class T,
class E>
619 struct expected_operations_base : expected_storage_base<T, E> {
620 using expected_storage_base<T, E>::expected_storage_base;
622 template <
class... Args>
void construct(Args &&...args) noexcept {
623 new (std::addressof(this->m_val)) T(std::forward<Args>(args)...);
624 this->m_has_val =
true;
627 template <
class Rhs>
void construct_with(Rhs &&rhs) noexcept {
628 new (std::addressof(this->m_val)) T(std::forward<Rhs>(rhs).get());
629 this->m_has_val =
true;
632 template <
class... Args>
void construct_error(Args &&...args) noexcept {
633 new (std::addressof(this->m_unexpect))
634 unexpected<E>(std::forward<Args>(args)...);
635 this->m_has_val =
false;
638 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
646 template <
class U = T,
647 detail::enable_if_t<std::is_nothrow_copy_constructible<U>::value>
649 void assign(
const expected_operations_base &rhs) noexcept {
650 if (!this->m_has_val && rhs.m_has_val) {
651 geterr().~unexpected<E>();
652 construct(rhs.get());
660 template <
class U = T,
661 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
662 std::is_nothrow_move_constructible<U>::value>
664 void assign(
const expected_operations_base &rhs) noexcept {
665 if (!this->m_has_val && rhs.m_has_val) {
667 geterr().~unexpected<E>();
668 construct(std::move(tmp));
679 template <
class U = T,
680 detail::enable_if_t<!std::is_nothrow_copy_constructible<U>::value &&
681 !std::is_nothrow_move_constructible<U>::value>
683 void assign(
const expected_operations_base &rhs) {
684 if (!this->m_has_val && rhs.m_has_val) {
685 auto tmp = std::move(geterr());
686 geterr().~unexpected<E>();
688 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
690 construct(rhs.get());
692 geterr() = std::move(tmp);
696 construct(rhs.get());
704 template <
class U = T,
705 detail::enable_if_t<std::is_nothrow_move_constructible<U>::value>
707 void assign(expected_operations_base &&rhs) noexcept {
708 if (!this->m_has_val && rhs.m_has_val) {
709 geterr().~unexpected<E>();
710 construct(std::move(rhs).
get());
712 assign_common(std::move(rhs));
716 template <
class U = T,
717 detail::enable_if_t<!std::is_nothrow_move_constructible<U>::value>
719 void assign(expected_operations_base &&rhs) {
720 if (!this->m_has_val && rhs.m_has_val) {
721 auto tmp = std::move(geterr());
722 geterr().~unexpected<E>();
723 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
725 construct(std::move(rhs).
get());
727 geterr() = std::move(tmp);
731 construct(std::move(rhs).
get());
734 assign_common(std::move(rhs));
741 void assign(
const expected_operations_base &rhs) noexcept {
742 if (!this->m_has_val && rhs.m_has_val) {
743 geterr().~unexpected<E>();
744 construct(rhs.get());
750 void assign(expected_operations_base &&rhs) noexcept {
751 if (!this->m_has_val && rhs.m_has_val) {
752 geterr().~unexpected<E>();
753 construct(std::move(rhs).
get());
755 assign_common(std::move(rhs));
762 template <
class Rhs>
void assign_common(Rhs &&rhs) {
763 if (this->m_has_val) {
765 get() = std::forward<Rhs>(rhs).get();
768 construct_error(std::forward<Rhs>(rhs).geterr());
771 if (!rhs.m_has_val) {
772 geterr() = std::forward<Rhs>(rhs).geterr();
777 bool has_value()
const {
return this->m_has_val; }
779 constexpr T &
get() & {
return this->m_val; }
780 constexpr
const T &
get() const & {
return this->m_val; }
781 constexpr T &&
get() && {
return std::move(this->m_val); }
782 constexpr
const T &&
get() const && {
return std::move(this->m_val); }
784 constexpr unexpected<E> &geterr() & {
785 return this->m_unexpect;
787 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
788 constexpr unexpected<E> &&geterr() && {
789 return std::move(this->m_unexpect);
791 constexpr
const unexpected<E> &&geterr() const && {
792 return std::move(this->m_unexpect);
795 constexpr
void destroy_val() {
get().~T(); }
801 struct expected_operations_base<void, E> : expected_storage_base<void, E> {
802 using expected_storage_base<void, E>::expected_storage_base;
804 template <
class... Args>
void construct() noexcept { this->m_has_val =
true; }
808 template <
class Rhs>
void construct_with(Rhs &&) noexcept {
809 this->m_has_val =
true;
812 template <
class... Args>
void construct_error(Args &&...args) noexcept {
813 new (std::addressof(this->m_unexpect))
814 unexpected<E>(std::forward<Args>(args)...);
815 this->m_has_val =
false;
818 template <
class Rhs>
void assign(Rhs &&rhs) noexcept {
819 if (!this->m_has_val) {
821 geterr().~unexpected<E>();
824 geterr() = std::forward<Rhs>(rhs).geterr();
827 if (!rhs.m_has_val) {
828 construct_error(std::forward<Rhs>(rhs).geterr());
833 bool has_value()
const {
return this->m_has_val; }
835 constexpr unexpected<E> &geterr() & {
836 return this->m_unexpect;
838 constexpr
const unexpected<E> &geterr() const & {
return this->m_unexpect; }
839 constexpr unexpected<E> &&geterr() && {
840 return std::move(this->m_unexpect);
842 constexpr
const unexpected<E> &&geterr() const && {
843 return std::move(this->m_unexpect);
846 constexpr
void destroy_val() {
853 template <
class T,
class E,
854 bool = is_void_or<T, GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)>::
855 value &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value>
856 struct expected_copy_base : expected_operations_base<T, E> {
857 using expected_operations_base<T, E>::expected_operations_base;
861 template <
class T,
class E>
862 struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
863 using expected_operations_base<T, E>::expected_operations_base;
865 expected_copy_base() =
default;
866 expected_copy_base(
const expected_copy_base &rhs)
867 : expected_operations_base<T, E>(no_init) {
868 if (rhs.has_value()) {
869 this->construct_with(rhs);
871 this->construct_error(rhs.geterr());
875 expected_copy_base(expected_copy_base &&rhs) =
default;
876 expected_copy_base &operator=(
const expected_copy_base &rhs) =
default;
877 expected_copy_base &operator=(expected_copy_base &&rhs) =
default;
881 template <
class T,
class E,
882 bool = is_void_or<T, std::is_trivially_move_constructible<T>>::value
883 &&std::is_trivially_move_constructible<E>::value>
884 struct expected_move_base : expected_copy_base<T, E> {
885 using expected_copy_base<T, E>::expected_copy_base;
888 template <
class T,
class E>
889 struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
890 using expected_copy_base<T, E>::expected_copy_base;
892 expected_move_base() =
default;
893 expected_move_base(
const expected_move_base &rhs) =
default;
895 expected_move_base(expected_move_base &&rhs) noexcept(
896 std::is_nothrow_move_constructible<T>::value)
897 : expected_copy_base<T, E>(no_init) {
898 if (rhs.has_value()) {
899 this->construct_with(std::move(rhs));
901 this->construct_error(std::move(rhs.geterr()));
904 expected_move_base &operator=(
const expected_move_base &rhs) =
default;
905 expected_move_base &operator=(expected_move_base &&rhs) =
default;
909 template <
class T,
class E,
911 T, conjunction<GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(T),
912 GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T),
913 GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(T)>>::value
914 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_ASSIGNABLE(E)::value
915 &&GUL14_EXPECTED_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(E)::value
916 &&GUL14_EXPECTED_IS_TRIVIALLY_DESTRUCTIBLE(E)::value>
917 struct expected_copy_assign_base : expected_move_base<T, E> {
918 using expected_move_base<T, E>::expected_move_base;
921 template <
class T,
class E>
922 struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
923 using expected_move_base<T, E>::expected_move_base;
925 expected_copy_assign_base() =
default;
926 expected_copy_assign_base(
const expected_copy_assign_base &rhs) =
default;
928 expected_copy_assign_base(expected_copy_assign_base &&rhs) =
default;
929 expected_copy_assign_base &operator=(
const expected_copy_assign_base &rhs) {
933 expected_copy_assign_base &
934 operator=(expected_copy_assign_base &&rhs) =
default;
938 template <
class T,
class E,
940 is_void_or<T, conjunction<std::is_trivially_destructible<T>,
941 std::is_trivially_move_constructible<T>,
942 std::is_trivially_move_assignable<T>>>::
943 value &&std::is_trivially_destructible<E>::value
944 &&std::is_trivially_move_constructible<E>::value
945 &&std::is_trivially_move_assignable<E>::value>
946 struct expected_move_assign_base : expected_copy_assign_base<T, E> {
947 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
950 template <
class T,
class E>
951 struct expected_move_assign_base<T, E, false>
952 : expected_copy_assign_base<T, E> {
953 using expected_copy_assign_base<T, E>::expected_copy_assign_base;
955 expected_move_assign_base() =
default;
956 expected_move_assign_base(
const expected_move_assign_base &rhs) =
default;
958 expected_move_assign_base(expected_move_assign_base &&rhs) =
default;
960 expected_move_assign_base &
961 operator=(
const expected_move_assign_base &rhs) =
default;
963 expected_move_assign_base &
964 operator=(expected_move_assign_base &&rhs) noexcept(
965 std::is_nothrow_move_constructible<T>::value
966 &&std::is_nothrow_move_assignable<T>::value) {
967 this->assign(std::move(rhs));
974 template <
class T,
class E,
975 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
976 std::is_copy_constructible<E>::value),
977 bool EnableMove = (is_move_constructible_or_void<T>::value &&
978 std::is_move_constructible<E>::value)>
979 struct expected_delete_ctor_base {
980 expected_delete_ctor_base() =
default;
981 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
982 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
983 expected_delete_ctor_base &
984 operator=(const expected_delete_ctor_base &) = default;
985 expected_delete_ctor_base &
986 operator=(expected_delete_ctor_base &&) noexcept = default;
989 template <class T, class E>
990 struct expected_delete_ctor_base<T, E, true, false> {
991 expected_delete_ctor_base() =
default;
992 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
default;
993 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
994 expected_delete_ctor_base &
995 operator=(const expected_delete_ctor_base &) = default;
996 expected_delete_ctor_base &
997 operator=(expected_delete_ctor_base &&) noexcept = default;
1000 template <class T, class E>
1001 struct expected_delete_ctor_base<T, E, false, true> {
1002 expected_delete_ctor_base() =
default;
1003 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1004 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = default;
1005 expected_delete_ctor_base &
1006 operator=(const expected_delete_ctor_base &) = default;
1007 expected_delete_ctor_base &
1008 operator=(expected_delete_ctor_base &&) noexcept = default;
1011 template <class T, class E>
1012 struct expected_delete_ctor_base<T, E, false, false> {
1013 expected_delete_ctor_base() =
default;
1014 expected_delete_ctor_base(
const expected_delete_ctor_base &) =
delete;
1015 expected_delete_ctor_base(expected_delete_ctor_base &&) noexcept = delete;
1016 expected_delete_ctor_base &
1017 operator=(const expected_delete_ctor_base &) = default;
1018 expected_delete_ctor_base &
1019 operator=(expected_delete_ctor_base &&) noexcept = default;
1025 template <class T, class E,
1026 bool EnableCopy = (is_copy_constructible_or_void<T>::value &&
1027 std::is_copy_constructible<E>::value &&
1028 is_copy_assignable_or_void<T>::value &&
1029 std::is_copy_assignable<E>::value),
1030 bool EnableMove = (is_move_constructible_or_void<T>::value &&
1031 std::is_move_constructible<E>::value &&
1032 is_move_assignable_or_void<T>::value &&
1033 std::is_move_assignable<E>::value)>
1034 struct expected_delete_assign_base {
1035 expected_delete_assign_base() =
default;
1036 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1037 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1039 expected_delete_assign_base &
1040 operator=(const expected_delete_assign_base &) = default;
1041 expected_delete_assign_base &
1042 operator=(expected_delete_assign_base &&) noexcept = default;
1045 template <class T, class E>
1046 struct expected_delete_assign_base<T, E, true, false> {
1047 expected_delete_assign_base() =
default;
1048 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1049 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1051 expected_delete_assign_base &
1052 operator=(const expected_delete_assign_base &) = default;
1053 expected_delete_assign_base &
1054 operator=(expected_delete_assign_base &&) noexcept = delete;
1057 template <class T, class E>
1058 struct expected_delete_assign_base<T, E, false, true> {
1059 expected_delete_assign_base() =
default;
1060 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1061 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1063 expected_delete_assign_base &
1064 operator=(const expected_delete_assign_base &) = delete;
1065 expected_delete_assign_base &
1066 operator=(expected_delete_assign_base &&) noexcept = default;
1069 template <class T, class E>
1070 struct expected_delete_assign_base<T, E, false, false> {
1071 expected_delete_assign_base() =
default;
1072 expected_delete_assign_base(
const expected_delete_assign_base &) =
default;
1073 expected_delete_assign_base(expected_delete_assign_base &&) noexcept =
1075 expected_delete_assign_base &
1076 operator=(const expected_delete_assign_base &) = delete;
1077 expected_delete_assign_base &
1078 operator=(expected_delete_assign_base &&) noexcept = delete;
1083 struct default_constructor_tag {
1084 explicit constexpr default_constructor_tag() =
default;
1090 template <
class T,
class E,
1092 std::is_default_constructible<T>::value || std::is_void<T>::value>
1093 struct expected_default_ctor_base {
1094 constexpr expected_default_ctor_base() noexcept = default;
1095 constexpr expected_default_ctor_base(
1096 expected_default_ctor_base const &) noexcept = default;
1097 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1099 expected_default_ctor_base &
1100 operator=(expected_default_ctor_base const &) noexcept = default;
1101 expected_default_ctor_base &
1102 operator=(expected_default_ctor_base &&) noexcept = default;
1104 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1108 template <
class T,
class E>
struct expected_default_ctor_base<T, E, false> {
1109 constexpr expected_default_ctor_base() noexcept = delete;
1110 constexpr expected_default_ctor_base(
1111 expected_default_ctor_base const &) noexcept = default;
1112 constexpr expected_default_ctor_base(expected_default_ctor_base &&) noexcept =
1114 expected_default_ctor_base &
1115 operator=(expected_default_ctor_base const &) noexcept = default;
1116 expected_default_ctor_base &
1117 operator=(expected_default_ctor_base &&) noexcept = default;
1119 constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
1123 template <
typename E>
1124 class bad_expected_access;
1126 template <>
class bad_expected_access<void> :
public std::exception
1129 virtual const char *what() const noexcept
override {
1130 return "Bad expected access";
1134 bad_expected_access() noexcept {}
1135 bad_expected_access(
const bad_expected_access&) =
default;
1136 bad_expected_access(bad_expected_access&&) =
default;
1137 bad_expected_access& operator=(
const bad_expected_access&) =
default;
1138 bad_expected_access& operator=(bad_expected_access&&) =
default;
1139 ~bad_expected_access() =
default;
1143 class bad_expected_access :
public bad_expected_access<void>
1146 explicit bad_expected_access(E e) : m_val(std::move(e)) {}
1148 const E &error() const & {
return m_val; }
1149 E &error() & {
return m_val; }
1150 const E &&error() const && {
return std::move(m_val); }
1151 E &&error() && {
return std::move(m_val); }
1157 template <
class T,
class E>
1158 class expected :
private detail::expected_move_assign_base<T, E>,
1159 private detail::expected_delete_ctor_base<T, E>,
1160 private detail::expected_delete_assign_base<T, E>,
1161 private detail::expected_default_ctor_base<T, E> {
1162 static_assert(!std::is_reference<T>::value,
"T must not be a reference");
1163 static_assert(!std::is_same<T, std::remove_cv<in_place_t>::type>::value,
1164 "T must not be in_place_t");
1165 static_assert(!std::is_same<T, std::remove_cv<unexpect_t>::type>::value,
1166 "T must not be unexpect_t");
1168 !std::is_same<T,
typename std::remove_cv<unexpected<E>>::type>::value,
1169 "T must not be unexpected<E>");
1170 static_assert(!std::is_reference<E>::value,
"E must not be a reference");
1172 T *valptr() {
return std::addressof(this->m_val); }
1173 const T *valptr()
const {
return std::addressof(this->m_val); }
1174 unexpected<E> *errptr() {
return std::addressof(this->m_unexpect); }
1175 const unexpected<E> *errptr()
const {
1176 return std::addressof(this->m_unexpect);
1179 template <
class U = T,
1180 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1181 constexpr U &val() {
1184 constexpr unexpected<E> &err() {
return this->m_unexpect; }
1186 template <
class U = T,
1187 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1188 constexpr
const U &val()
const {
1191 constexpr
const unexpected<E> &err()
const {
return this->m_unexpect; }
1193 using impl_base = detail::expected_move_assign_base<T, E>;
1194 using ctor_base = detail::expected_default_ctor_base<T, E>;
1197 typedef T value_type;
1198 typedef E error_type;
1199 typedef unexpected<E> unexpected_type;
1201 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1203 template <
class F> constexpr
auto and_then(F &&f) & {
1204 return and_then_impl(*
this, std::forward<F>(f));
1206 template <
class F> constexpr
auto and_then(F &&f) && {
1207 return and_then_impl(std::move(*
this), std::forward<F>(f));
1209 template <
class F> constexpr
auto and_then(F &&f)
const & {
1210 return and_then_impl(*
this, std::forward<F>(f));
1212 template <
class F> constexpr
auto and_then(F &&f)
const && {
1213 return and_then_impl(std::move(*
this), std::forward<F>(f));
1220 and_then(F &&f) & -> decltype(and_then_impl(std::declval<expected &>(),
1221 std::forward<F>(f))) {
1222 return and_then_impl(*
this, std::forward<F>(f));
1226 and_then(F &&f) && -> decltype(and_then_impl(std::declval<expected &&>(),
1227 std::forward<F>(f))) {
1228 return and_then_impl(std::move(*
this), std::forward<F>(f));
1231 constexpr
auto and_then(F &&f)
const & -> decltype(and_then_impl(
1232 std::declval<expected const &>(), std::forward<F>(f))) {
1233 return and_then_impl(*
this, std::forward<F>(f));
1236 constexpr
auto and_then(F &&f)
const && -> decltype(and_then_impl(
1237 std::declval<expected const &&>(), std::forward<F>(f))) {
1238 return and_then_impl(std::move(*
this), std::forward<F>(f));
1243 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1244 template <
class F> constexpr
auto map(F &&f) & {
1245 return expected_map_impl(*
this, std::forward<F>(f));
1247 template <
class F> constexpr
auto map(F &&f) && {
1248 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1250 template <
class F> constexpr
auto map(F &&f)
const & {
1251 return expected_map_impl(*
this, std::forward<F>(f));
1253 template <
class F> constexpr
auto map(F &&f)
const && {
1254 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1258 constexpr decltype(expected_map_impl(
1259 std::declval<expected &>(), std::declval<F &&>()))
1261 return expected_map_impl(*
this, std::forward<F>(f));
1264 constexpr decltype(expected_map_impl(std::declval<expected>(),
1265 std::declval<F &&>()))
1267 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1270 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1271 std::declval<F &&>()))
1272 map(F &&f) const & {
1273 return expected_map_impl(*
this, std::forward<F>(f));
1276 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1277 std::declval<F &&>()))
1278 map(F &&f) const && {
1279 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1283 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1284 template <
class F> constexpr
auto transform(F &&f) & {
1285 return expected_map_impl(*
this, std::forward<F>(f));
1287 template <
class F> constexpr
auto transform(F &&f) && {
1288 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1290 template <
class F> constexpr
auto transform(F &&f)
const & {
1291 return expected_map_impl(*
this, std::forward<F>(f));
1293 template <
class F> constexpr
auto transform(F &&f)
const && {
1294 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1298 constexpr decltype(expected_map_impl(
1299 std::declval<expected &>(), std::declval<F &&>()))
1300 transform(F &&f) & {
1301 return expected_map_impl(*
this, std::forward<F>(f));
1304 constexpr decltype(expected_map_impl(std::declval<expected>(),
1305 std::declval<F &&>()))
1306 transform(F &&f) && {
1307 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1310 constexpr decltype(expected_map_impl(std::declval<const expected &>(),
1311 std::declval<F &&>()))
1312 transform(F &&f) const & {
1313 return expected_map_impl(*
this, std::forward<F>(f));
1316 constexpr decltype(expected_map_impl(std::declval<const expected &&>(),
1317 std::declval<F &&>()))
1318 transform(F &&f) const && {
1319 return expected_map_impl(std::move(*
this), std::forward<F>(f));
1323 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1324 template <
class F> constexpr
auto map_error(F &&f) & {
1325 return map_error_impl(*
this, std::forward<F>(f));
1327 template <
class F> constexpr
auto map_error(F &&f) && {
1328 return map_error_impl(std::move(*
this), std::forward<F>(f));
1330 template <
class F> constexpr
auto map_error(F &&f)
const & {
1331 return map_error_impl(*
this, std::forward<F>(f));
1333 template <
class F> constexpr
auto map_error(F &&f)
const && {
1334 return map_error_impl(std::move(*
this), std::forward<F>(f));
1338 constexpr decltype(map_error_impl(std::declval<expected &>(),
1339 std::declval<F &&>()))
1340 map_error(F &&f) & {
1341 return map_error_impl(*
this, std::forward<F>(f));
1344 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1345 std::declval<F &&>()))
1346 map_error(F &&f) && {
1347 return map_error_impl(std::move(*
this), std::forward<F>(f));
1350 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1351 std::declval<F &&>()))
1352 map_error(F &&f) const & {
1353 return map_error_impl(*
this, std::forward<F>(f));
1356 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1357 std::declval<F &&>()))
1358 map_error(F &&f) const && {
1359 return map_error_impl(std::move(*
this), std::forward<F>(f));
1362 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
1363 template <
class F> constexpr
auto transform_error(F &&f) & {
1364 return map_error_impl(*
this, std::forward<F>(f));
1366 template <
class F> constexpr
auto transform_error(F &&f) && {
1367 return map_error_impl(std::move(*
this), std::forward<F>(f));
1369 template <
class F> constexpr
auto transform_error(F &&f)
const & {
1370 return map_error_impl(*
this, std::forward<F>(f));
1372 template <
class F> constexpr
auto transform_error(F &&f)
const && {
1373 return map_error_impl(std::move(*
this), std::forward<F>(f));
1377 constexpr decltype(map_error_impl(std::declval<expected &>(),
1378 std::declval<F &&>()))
1379 transform_error(F &&f) & {
1380 return map_error_impl(*
this, std::forward<F>(f));
1383 constexpr decltype(map_error_impl(std::declval<expected &&>(),
1384 std::declval<F &&>()))
1385 transform_error(F &&f) && {
1386 return map_error_impl(std::move(*
this), std::forward<F>(f));
1389 constexpr decltype(map_error_impl(std::declval<const expected &>(),
1390 std::declval<F &&>()))
1391 transform_error(F &&f) const & {
1392 return map_error_impl(*
this, std::forward<F>(f));
1395 constexpr decltype(map_error_impl(std::declval<const expected &&>(),
1396 std::declval<F &&>()))
1397 transform_error(F &&f) const && {
1398 return map_error_impl(std::move(*
this), std::forward<F>(f));
1401 template <
class F> expected constexpr or_else(F &&f) & {
1402 return or_else_impl(*
this, std::forward<F>(f));
1405 template <
class F> expected constexpr or_else(F &&f) && {
1406 return or_else_impl(std::move(*
this), std::forward<F>(f));
1409 template <
class F> expected constexpr or_else(F &&f)
const & {
1410 return or_else_impl(*
this, std::forward<F>(f));
1413 template <
class F> expected constexpr or_else(F &&f)
const && {
1414 return or_else_impl(std::move(*
this), std::forward<F>(f));
1417 constexpr expected() =
default;
1418 constexpr expected(
const expected &rhs) =
default;
1419 constexpr expected(expected &&rhs) =
default;
1420 expected &operator=(
const expected &rhs) =
default;
1421 expected &operator=(expected &&rhs) =
default;
1423 template <
class... Args,
1424 detail::enable_if_t<std::is_constructible<T, Args &&...>::value> * =
1426 constexpr expected(in_place_t, Args &&...args)
1427 : impl_base(in_place, std::forward<Args>(args)...),
1428 ctor_base(detail::default_constructor_tag{}) {}
1430 template <
class U,
class... Args,
1431 detail::enable_if_t<std::is_constructible<
1432 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1433 constexpr expected(in_place_t, std::initializer_list<U> il, Args &&...args)
1434 : impl_base(in_place, il, std::forward<Args>(args)...),
1435 ctor_base(detail::default_constructor_tag{}) {}
1437 template <
class G = E,
1438 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1440 detail::enable_if_t<!std::is_convertible<const G &, E>::value> * =
1442 explicit constexpr expected(
const unexpected<G> &e)
1443 : impl_base(unexpect, e.value()),
1444 ctor_base(detail::default_constructor_tag{}) {}
1448 detail::enable_if_t<std::is_constructible<E, const G &>::value> * =
1450 detail::enable_if_t<std::is_convertible<const G &, E>::value> * =
nullptr>
1451 constexpr expected(unexpected<G>
const &e)
1452 : impl_base(unexpect, e.value()),
1453 ctor_base(detail::default_constructor_tag{}) {}
1457 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1458 detail::enable_if_t<!std::is_convertible<G &&, E>::value> * =
nullptr>
1459 explicit constexpr expected(unexpected<G> &&e) noexcept(
1460 std::is_nothrow_constructible<E, G &&>::value)
1461 : impl_base(unexpect, std::move(e.value())),
1462 ctor_base(detail::default_constructor_tag{}) {}
1466 detail::enable_if_t<std::is_constructible<E, G &&>::value> * =
nullptr,
1467 detail::enable_if_t<std::is_convertible<G &&, E>::value> * =
nullptr>
1468 constexpr expected(unexpected<G> &&e) noexcept(
1469 std::is_nothrow_constructible<E, G &&>::value)
1470 : impl_base(unexpect, std::move(e.value())),
1471 ctor_base(detail::default_constructor_tag{}) {}
1473 template <
class... Args,
1474 detail::enable_if_t<std::is_constructible<E, Args &&...>::value> * =
1476 constexpr
explicit expected(unexpect_t, Args &&...args)
1477 : impl_base(unexpect, std::forward<Args>(args)...),
1478 ctor_base(detail::default_constructor_tag{}) {}
1480 template <
class U,
class... Args,
1481 detail::enable_if_t<std::is_constructible<
1482 E, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1483 constexpr
explicit expected(unexpect_t, std::initializer_list<U> il,
1485 : impl_base(unexpect, il, std::forward<Args>(args)...),
1486 ctor_base(detail::default_constructor_tag{}) {}
1488 template <
class U,
class G,
1489 detail::enable_if_t<!(std::is_convertible<U const &, T>::value &&
1490 std::is_convertible<G const &, E>::value)> * =
1492 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1494 explicit constexpr expected(
const expected<U, G> &rhs)
1495 : ctor_base(detail::default_constructor_tag{}) {
1496 if (rhs.has_value()) {
1497 this->construct(*rhs);
1499 this->construct_error(rhs.error());
1503 template <
class U,
class G,
1504 detail::enable_if_t<(std::is_convertible<U const &, T>::value &&
1505 std::is_convertible<G const &, E>::value)> * =
1507 detail::expected_enable_from_other<T, E, U, G, const U &, const G &>
1509 constexpr expected(
const expected<U, G> &rhs)
1510 : ctor_base(detail::default_constructor_tag{}) {
1511 if (rhs.has_value()) {
1512 this->construct(*rhs);
1514 this->construct_error(rhs.error());
1520 detail::enable_if_t<!(std::is_convertible<U &&, T>::value &&
1521 std::is_convertible<G &&, E>::value)> * =
nullptr,
1522 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1523 explicit constexpr expected(expected<U, G> &&rhs)
1524 : ctor_base(detail::default_constructor_tag{}) {
1525 if (rhs.has_value()) {
1526 this->construct(std::move(*rhs));
1528 this->construct_error(std::move(rhs.error()));
1534 detail::enable_if_t<(std::is_convertible<U &&, T>::value &&
1535 std::is_convertible<G &&, E>::value)> * =
nullptr,
1536 detail::expected_enable_from_other<T, E, U, G, U &&, G &&> * =
nullptr>
1537 constexpr expected(expected<U, G> &&rhs)
1538 : ctor_base(detail::default_constructor_tag{}) {
1539 if (rhs.has_value()) {
1540 this->construct(std::move(*rhs));
1542 this->construct_error(std::move(rhs.error()));
1548 detail::enable_if_t<!std::is_convertible<U &&, T>::value> * =
nullptr,
1549 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1550 explicit constexpr expected(U &&v)
1551 : expected(in_place, std::forward<U>(v)) {}
1555 detail::enable_if_t<std::is_convertible<U &&, T>::value> * =
nullptr,
1556 detail::expected_enable_forward_value<T, E, U> * =
nullptr>
1557 constexpr expected(U &&v)
1558 : expected(in_place, std::forward<U>(v)) {}
1561 class U = T,
class G = T,
1562 detail::enable_if_t<std::is_nothrow_constructible<T, U &&>::value> * =
1564 detail::enable_if_t<!std::is_void<G>::value> * =
nullptr,
1565 detail::enable_if_t<
1566 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1567 !detail::conjunction<std::is_scalar<T>,
1568 std::is_same<T, detail::decay_t<U>>>::value &&
1569 std::is_constructible<T, U>::value &&
1570 std::is_assignable<G &, U>::value &&
1571 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1572 expected &
operator=(U &&v) {
1574 val() = std::forward<U>(v);
1576 err().~unexpected<E>();
1577 ::new (valptr()) T(std::forward<U>(v));
1578 this->m_has_val = true;
1585 class U = T, class G = T,
1586 detail::enable_if_t<!std::is_nothrow_constructible<T, U &&>::value> * =
1588 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr,
1589 detail::enable_if_t<
1590 (!std::is_same<expected<T, E>, detail::decay_t<U>>::value &&
1591 !detail::conjunction<std::is_scalar<T>,
1592 std::is_same<T, detail::decay_t<U>>>::value &&
1593 std::is_constructible<T, U>::value &&
1594 std::is_assignable<G &, U>::value &&
1595 std::is_nothrow_move_constructible<E>::value)> * =
nullptr>
1596 expected &operator=(U &&v) {
1598 val() = std::forward<U>(v);
1600 auto tmp = std::move(err());
1601 err().~unexpected<E>();
1603 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1605 ::new (valptr()) T(std::forward<U>(v));
1606 this->m_has_val = true;
1608 err() = std::move(tmp);
1612 ::new (valptr()) T(std::forward<U>(v));
1613 this->m_has_val = true;
1620 template <
class G = E,
1621 detail::enable_if_t<std::is_nothrow_copy_constructible<G>::value &&
1622 std::is_assignable<G &, G>::value> * =
nullptr>
1623 expected &operator=(
const unexpected<G> &rhs) {
1627 this->destroy_val();
1628 ::new (errptr()) unexpected<E>(rhs);
1629 this->m_has_val = false;
1635 template <class G = E,
1636 detail::enable_if_t<std::is_nothrow_move_constructible<G>::value &&
1637 std::is_move_assignable<G>::value> * =
nullptr>
1638 expected &operator=(unexpected<G> &&rhs) noexcept {
1640 err() = std::move(rhs);
1642 this->destroy_val();
1643 ::new (errptr()) unexpected<E>(std::move(rhs));
1644 this->m_has_val = false;
1650 template <class... Args, detail::enable_if_t<std::is_nothrow_constructible<
1651 T, Args &&...>::value> * =
nullptr>
1652 void emplace(Args &&...args) {
1656 err().~unexpected<E>();
1657 this->m_has_val =
true;
1659 ::new (valptr()) T(std::forward<Args>(args)...);
1662 template <class... Args, detail::enable_if_t<!std::is_nothrow_constructible<
1663 T, Args &&...>::value> * =
nullptr>
1664 void emplace(Args &&...args) {
1667 ::new (valptr()) T(std::forward<Args>(args)...);
1669 auto tmp = std::move(err());
1670 err().~unexpected<E>();
1672 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1674 ::new (valptr()) T(std::forward<Args>(args)...);
1675 this->m_has_val = true;
1677 err() = std::move(tmp);
1681 ::new (valptr()) T(std::forward<Args>(args)...);
1682 this->m_has_val = true;
1687 template <
class U,
class... Args,
1688 detail::enable_if_t<std::is_nothrow_constructible<
1689 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1690 void emplace(std::initializer_list<U> il, Args &&...args) {
1692 T t(il, std::forward<Args>(args)...);
1693 val() = std::move(t);
1695 err().~unexpected<E>();
1696 ::new (valptr()) T(il, std::forward<Args>(args)...);
1697 this->m_has_val = true;
1701 template <class U, class... Args,
1702 detail::enable_if_t<!std::is_nothrow_constructible<
1703 T, std::initializer_list<U> &, Args &&...>::value> * =
nullptr>
1704 void emplace(std::initializer_list<U> il, Args &&...args) {
1706 T t(il, std::forward<Args>(args)...);
1707 val() = std::move(t);
1709 auto tmp = std::move(err());
1710 err().~unexpected<E>();
1712 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1714 ::new (valptr()) T(il, std::forward<Args>(args)...);
1715 this->m_has_val = true;
1717 err() = std::move(tmp);
1721 ::new (valptr()) T(il, std::forward<Args>(args)...);
1722 this->m_has_val = true;
1728 using t_is_void = std::true_type;
1729 using t_is_not_void = std::false_type;
1730 using t_is_nothrow_move_constructible = std::true_type;
1731 using move_constructing_t_can_throw = std::false_type;
1732 using e_is_nothrow_move_constructible = std::true_type;
1733 using move_constructing_e_can_throw = std::false_type;
1735 void swap_where_both_have_value(expected & , t_is_void) noexcept {
1739 void swap_where_both_have_value(expected &rhs, t_is_not_void) {
1741 swap(val(), rhs.val());
1744 void swap_where_only_one_has_value(expected &rhs, t_is_void) noexcept(
1745 std::is_nothrow_move_constructible<E>::value) {
1746 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1747 rhs.err().~unexpected_type();
1748 std::
swap(this->m_has_val, rhs.m_has_val);
1751 void swap_where_only_one_has_value(expected &rhs, t_is_not_void) {
1752 swap_where_only_one_has_value_and_t_is_not_void(
1753 rhs,
typename std::is_nothrow_move_constructible<T>::type{},
1754 typename std::is_nothrow_move_constructible<E>::type{});
1757 void swap_where_only_one_has_value_and_t_is_not_void(
1758 expected &rhs, t_is_nothrow_move_constructible,
1759 e_is_nothrow_move_constructible) noexcept {
1760 auto temp = std::move(val());
1762 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1763 rhs.err().~unexpected_type();
1764 ::new (rhs.valptr()) T(std::move(temp));
1765 std::
swap(this->m_has_val, rhs.m_has_val);
1768 void swap_where_only_one_has_value_and_t_is_not_void(
1769 expected &rhs, t_is_nothrow_move_constructible,
1770 move_constructing_e_can_throw) {
1771 auto temp = std::move(val());
1773 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1775 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1776 rhs.err().~unexpected_type();
1777 ::new (rhs.valptr()) T(std::move(temp));
1778 std::
swap(this->m_has_val, rhs.m_has_val);
1780 val() = std::move(temp);
1784 ::new (errptr()) unexpected_type(std::move(rhs.err()));
1785 rhs.err().~unexpected_type();
1786 ::new (rhs.valptr()) T(std::move(temp));
1787 std::
swap(this->m_has_val, rhs.m_has_val);
1791 void swap_where_only_one_has_value_and_t_is_not_void(
1792 expected &rhs, move_constructing_t_can_throw,
1793 e_is_nothrow_move_constructible) {
1794 auto temp = std::move(rhs.err());
1795 rhs.err().~unexpected_type();
1796 #ifdef GUL14_EXPECTED_EXCEPTIONS_ENABLED
1798 ::new (rhs.valptr()) T(std::move(val()));
1800 ::new (errptr()) unexpected_type(std::move(temp));
1801 std::
swap(this->m_has_val, rhs.m_has_val);
1803 rhs.err() = std::move(temp);
1807 ::new (rhs.valptr()) T(std::move(val()));
1809 ::new (errptr()) unexpected_type(std::move(temp));
1810 std::
swap(this->m_has_val, rhs.m_has_val);
1815 template <
class OT = T,
class OE = E>
1816 detail::enable_if_t<detail::is_swappable<OT>::value &&
1817 detail::is_swappable<OE>::value &&
1818 (std::is_nothrow_move_constructible<OT>::value ||
1819 std::is_nothrow_move_constructible<OE>::value)>
1820 swap(expected &rhs) noexcept(
1821 std::is_nothrow_move_constructible<T>::value
1822 &&detail::is_nothrow_swappable<T>::value
1823 &&std::is_nothrow_move_constructible<E>::value
1824 &&detail::is_nothrow_swappable<E>::value) {
1825 if (has_value() && rhs.has_value()) {
1826 swap_where_both_have_value(rhs,
typename std::is_void<T>::type{});
1827 }
else if (!has_value() && rhs.has_value()) {
1829 }
else if (has_value()) {
1830 swap_where_only_one_has_value(rhs,
typename std::is_void<T>::type{});
1833 swap(err(), rhs.err());
1837 constexpr
const T *operator->()
const {
1838 assert(has_value());
1841 constexpr T *operator->() {
1842 assert(has_value());
1846 template <
class U = T,
1847 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1848 constexpr
const U &operator*() const & {
1849 assert(has_value());
1852 template <
class U = T,
1853 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1854 constexpr U &operator*() & {
1855 assert(has_value());
1858 template <
class U = T,
1859 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1860 constexpr
const U &&operator*() const && {
1861 assert(has_value());
1862 return std::move(val());
1864 template <
class U = T,
1865 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1866 constexpr U &&operator*() && {
1867 assert(has_value());
1868 return std::move(val());
1871 constexpr
bool has_value() const noexcept {
return this->m_has_val; }
1872 constexpr
explicit operator bool() const noexcept {
return this->m_has_val; }
1874 template <
class U = T,
1875 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1876 constexpr
const U &value() const & {
1878 detail::throw_exception(bad_expected_access<E>(err().value()));
1881 template <
class U = T,
1882 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1883 constexpr U &value() & {
1885 detail::throw_exception(bad_expected_access<E>(err().value()));
1888 template <
class U = T,
1889 detail::enable_if_t<!std::is_void<U>::value> * =
nullptr>
1890 constexpr
const U &&value() const && {
1892 detail::throw_exception(bad_expected_access<E>(std::move(err()).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 &&value() && {
1899 detail::throw_exception(bad_expected_access<E>(std::move(err()).value()));
1900 return std::move(val());
1903 constexpr
const E &error() const & {
1904 assert(!has_value());
1905 return err().value();
1907 constexpr E &error() & {
1908 assert(!has_value());
1909 return err().value();
1911 constexpr
const E &&error() const && {
1912 assert(!has_value());
1913 return std::move(err().value());
1915 constexpr E &&error() && {
1916 assert(!has_value());
1917 return std::move(err().value());
1920 template <
class U> constexpr T value_or(U &&v)
const & {
1921 static_assert(std::is_copy_constructible<T>::value &&
1922 std::is_convertible<U &&, T>::value,
1923 "T must be copy-constructible and convertible to from U&&");
1924 return bool(*
this) ? **this :
static_cast<T
>(std::forward<U>(v));
1926 template <
class U> constexpr T value_or(U &&v) && {
1927 static_assert(std::is_move_constructible<T>::value &&
1928 std::is_convertible<U &&, T>::value,
1929 "T must be move-constructible and convertible to from U&&");
1930 return bool(*
this) ? std::move(**
this) : static_cast<T>(std::forward<U>(v));
1935 template <
class Exp>
using exp_t =
typename detail::decay_t<Exp>::value_type;
1936 template <
class Exp>
using err_t =
typename detail::decay_t<Exp>::error_type;
1937 template <
class Exp,
class Ret>
using ret_t = expected<Ret, err_t<Exp>>;
1939 template <
class Exp,
class F,
1940 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1941 class Ret = decltype(
invoke(std::declval<F>(),
1942 *std::declval<Exp>()))>
1943 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1944 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1946 return exp.has_value()
1947 ?
invoke(std::forward<F>(f), *std::forward<Exp>(exp))
1948 : Ret(unexpect, std::forward<Exp>(exp).error());
1951 template <
class Exp,
class F,
1952 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
1953 class Ret = decltype(
invoke(std::declval<F>()))>
1954 constexpr
auto and_then_impl(Exp &&exp, F &&f) {
1955 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
1957 return exp.has_value() ?
invoke(std::forward<F>(f))
1958 : Ret(unexpect, std::forward<Exp>(exp).error());
1961 template <
class Exp,
class F,
1962 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1963 class Ret = decltype(
invoke(std::declval<F>(),
1964 *std::declval<Exp>())),
1965 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1966 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
1967 using result = ret_t<Exp, detail::decay_t<Ret>>;
1968 return exp.has_value() ? result(
invoke(std::forward<F>(f),
1969 *std::forward<Exp>(exp)))
1970 : result(unexpect, std::forward<Exp>(exp).error());
1973 template <
class Exp,
class F,
1974 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
1975 class Ret = decltype(
invoke(std::declval<F>(),
1976 *std::declval<Exp>())),
1977 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
1978 auto expected_map_impl(Exp &&exp, F &&f) {
1979 using result = expected<void, err_t<Exp>>;
1980 if (exp.has_value()) {
1981 invoke(std::forward<F>(f), *std::forward<Exp>(exp));
1985 return result(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(
invoke(std::declval<F>())),
1991 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
1992 constexpr
auto expected_map_impl(Exp &&exp, F &&f) {
1993 using result = ret_t<Exp, detail::decay_t<Ret>>;
1994 return exp.has_value() ? result(
invoke(std::forward<F>(f)))
1995 : result(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(
invoke(std::declval<F>())),
2001 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2002 auto expected_map_impl(Exp &&exp, F &&f) {
2003 using result = expected<void, err_t<Exp>>;
2004 if (exp.has_value()) {
2005 invoke(std::forward<F>(f));
2009 return result(unexpect, std::forward<Exp>(exp).error());
2012 #if !defined(GUL14_EXPECTED_GCC54) && !defined(GUL14_EXPECTED_GCC55)
2013 template <
class Exp,
class F,
2014 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2015 class Ret = decltype(
invoke(std::declval<F>(),
2016 std::declval<Exp>().error())),
2017 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2018 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2019 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2020 return exp.has_value()
2021 ? result(*std::forward<Exp>(exp))
2022 : result(unexpect,
invoke(std::forward<F>(f),
2023 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(
invoke(std::declval<F>(),
2028 std::declval<Exp>().error())),
2029 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2030 auto map_error_impl(Exp &&exp, F &&f) {
2031 using result = expected<exp_t<Exp>, monostate>;
2032 if (exp.has_value()) {
2033 return result(*std::forward<Exp>(exp));
2036 invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2037 return result(unexpect, monostate{});
2039 template <
class Exp,
class F,
2040 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2041 class Ret = decltype(
invoke(std::declval<F>(),
2042 std::declval<Exp>().error())),
2043 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2044 constexpr
auto map_error_impl(Exp &&exp, F &&f) {
2045 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2046 return exp.has_value()
2048 : result(unexpect,
invoke(std::forward<F>(f),
2049 std::forward<Exp>(exp).error()));
2051 template <
class Exp,
class F,
2052 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2053 class Ret = decltype(
invoke(std::declval<F>(),
2054 std::declval<Exp>().error())),
2055 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2056 auto map_error_impl(Exp &&exp, F &&f) {
2057 using result = expected<exp_t<Exp>, monostate>;
2058 if (exp.has_value()) {
2062 invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2063 return result(unexpect, monostate{});
2066 template <
class Exp,
class F,
2067 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2068 class Ret = decltype(
invoke(std::declval<F>(),
2069 std::declval<Exp>().error())),
2070 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2071 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2072 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2073 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2075 return exp.has_value()
2076 ? result(*std::forward<Exp>(exp))
2077 : result(unexpect,
invoke(std::forward<F>(f),
2078 std::forward<Exp>(exp).error()));
2081 template <
class Exp,
class F,
2082 detail::enable_if_t<!std::is_void<exp_t<Exp>>::value> * =
nullptr,
2083 class Ret = decltype(
invoke(std::declval<F>(),
2084 std::declval<Exp>().error())),
2085 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2086 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2087 using result = expected<exp_t<Exp>, monostate>;
2088 if (exp.has_value()) {
2089 return result(*std::forward<Exp>(exp));
2092 invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2093 return result(unexpect, monostate{});
2096 template <
class Exp,
class F,
2097 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2098 class Ret = decltype(
invoke(std::declval<F>(),
2099 std::declval<Exp>().error())),
2100 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2101 constexpr
auto map_error_impl(Exp &&exp, F &&f)
2102 -> expected<exp_t<Exp>, detail::decay_t<Ret>> {
2103 using result = expected<exp_t<Exp>, detail::decay_t<Ret>>;
2105 return exp.has_value()
2107 : result(unexpect,
invoke(std::forward<F>(f), std::forward<Exp>(exp).error()));
2110 template <
class Exp,
class F,
2111 detail::enable_if_t<std::is_void<exp_t<Exp>>::value> * =
nullptr,
2112 class Ret = decltype(
invoke(std::declval<F>(),
2113 std::declval<Exp>().error())),
2114 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2115 auto map_error_impl(Exp &&exp, F &&f) -> expected<exp_t<Exp>, monostate> {
2116 using result = expected<exp_t<Exp>, monostate>;
2117 if (exp.has_value()) {
2121 invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2122 return result(unexpect, monostate{});
2126 template <
class Exp,
class F,
2127 class Ret = decltype(
invoke(std::declval<F>(),
2128 std::declval<Exp>().error())),
2129 detail::enable_if_t<!std::is_void<Ret>::value> * =
nullptr>
2130 constexpr
auto or_else_impl(Exp &&exp, F &&f) {
2131 static_assert(detail::is_expected<Ret>::value,
"F must return an expected");
2132 return exp.has_value() ? std::forward<Exp>(exp)
2133 :
invoke(std::forward<F>(f), std::forward<Exp>(exp).error());
2136 template <
class Exp,
class F,
2137 class Ret = decltype(
invoke(std::declval<F>(),
2138 std::declval<Exp>().error())),
2139 detail::enable_if_t<std::is_void<Ret>::value> * =
nullptr>
2140 detail::decay_t<Exp> or_else_impl(Exp &&exp, F &&f) {
2141 return exp.has_value() ? std::forward<Exp>(exp)
2142 : (
invoke(std::forward<F>(f), std::forward<Exp>(exp).error()),
2143 std::forward<Exp>(exp));
2148 template <
class T,
class E,
class U,
class F>
2149 constexpr
bool operator==(
const expected<T, E> &lhs,
2150 const expected<U, F> &rhs) {
2151 return (lhs.has_value() != rhs.has_value())
2153 : (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
2155 template <
class T,
class E,
class U,
class F>
2156 constexpr
bool operator!=(
const expected<T, E> &lhs,
2157 const expected<U, F> &rhs) {
2158 return (lhs.has_value() != rhs.has_value())
2160 : (!lhs.has_value() ? lhs.error() != rhs.error() : *lhs != *rhs);
2162 template <
class E,
class F>
2163 constexpr
bool operator==(
const expected<void, E> &lhs,
2164 const expected<void, F> &rhs) {
2165 return (lhs.has_value() != rhs.has_value())
2167 : (!lhs.has_value() ? lhs.error() == rhs.error() :
true);
2169 template <
class E,
class F>
2170 constexpr
bool operator!=(
const expected<void, E> &lhs,
2171 const expected<void, F> &rhs) {
2172 return (lhs.has_value() != rhs.has_value())
2174 : (!lhs.has_value() ? lhs.error() == rhs.error() :
false);
2177 template <
class T,
class E,
class U>
2178 constexpr
bool operator==(
const expected<T, E> &x,
const U &v) {
2179 return x.has_value() ? *x == v :
false;
2181 template <
class T,
class E,
class U>
2182 constexpr
bool operator==(
const U &v,
const expected<T, E> &x) {
2183 return x.has_value() ? *x == v :
false;
2185 template <
class T,
class E,
class U>
2186 constexpr
bool operator!=(
const expected<T, E> &x,
const U &v) {
2187 return x.has_value() ? *x != v :
true;
2189 template <
class T,
class E,
class U>
2190 constexpr
bool operator!=(
const U &v,
const expected<T, E> &x) {
2191 return x.has_value() ? *x != v :
true;
2194 template <
class T,
class E>
2195 constexpr
bool operator==(
const expected<T, E> &x,
const unexpected<E> &e) {
2196 return x.has_value() ? false : x.error() == e.value();
2198 template <
class T,
class E>
2199 constexpr
bool operator==(
const unexpected<E> &e,
const expected<T, E> &x) {
2200 return x.has_value() ? false : x.error() == e.value();
2202 template <
class T,
class E>
2203 constexpr
bool operator!=(
const expected<T, E> &x,
const unexpected<E> &e) {
2204 return x.has_value() ? true : x.error() != e.value();
2206 template <
class T,
class E>
2207 constexpr
bool operator!=(
const unexpected<E> &e,
const expected<T, E> &x) {
2208 return x.has_value() ? true : x.error() != e.value();
2211 template <
class T,
class E,
2212 detail::enable_if_t<(std::is_void<T>::value ||
2213 std::is_move_constructible<T>::value) &&
2214 detail::is_swappable<T>::value &&
2215 std::is_move_constructible<E>::value &&
2216 detail::is_swappable<E>::value> * =
nullptr>
2217 void swap(expected<T, E> &lhs,
2218 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
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(detail_invoke::invoke(std::forward< F >(f), std::forward< Args >(args)...))
Invoke a callable object f with the given arguments.
Definition: traits.h:201
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.