11#include <initializer_list>
19#define likely(x) __builtin_expect(static_cast<long int>((x)), 1)
20#define unlikely(x) __builtin_expect(reinterpret_cast<long int>((x)), 0)
23#define _DEXPECTED_THROW_OR_ABORT(_EXC) (throw(_EXC))
25#define _DEXPECTED_THROW_OR_ABORT(_EXC) (std::abort())
28template <
typename T,
typename E>
35using _bool_constant = std::integral_constant<bool, v>;
40enum class emplace_tag { USE_EMPLACE };
45enum class dunexpected_tag { DUNEXPECTED };
47template <
typename Type>
50 using type =
typename std::remove_cv<typename std::remove_reference<Type>::type>::type;
68 const char *what()
const noexcept override {
return "bad access to DExpected without value"; }
76 : m_error(std::move(_e))
80 E &error() &
noexcept {
return m_error; }
81 const E &error()
const &
noexcept {
return m_error; }
83 E error() &&
noexcept {
return std::move(m_error); }
84 const E error()
const &&
noexcept {
return std::move(m_error); }
90template <
typename Type,
typename... Args>
91auto construct_at(Type *p, Args &&...args)
noexcept(
noexcept(::new((
void *)0) Type(std::declval<Args>()...)))
92 ->
decltype(::new((
void *)0) Type(std::declval<Args>()...))
94 return ::new ((
void *)p) Type(std::forward<Args>(args)...);
97namespace __dexpected {
98template <
typename ObjType>
99void destroy_at_obj(ObjType *p)
104template <
typename ArrType>
105void destroy_at_arr(ArrType *p)
107 for (
auto &elem : *p)
108 destroy_at_obj(std::addressof(elem));
112template <typename Type, typename std::enable_if<std::is_array<Type>::value,
bool>::type =
true>
113void destroy_at(Type *p)
115 __dexpected::destroy_at_arr(p);
118template <typename Type, typename std::enable_if<!std::is_array<Type>::value,
bool>::type =
true>
119void destroy_at(Type *p)
121 __dexpected::destroy_at_obj(p);
124namespace __dexpected {
128 static_assert(std::is_nothrow_move_constructible<T>::value,
"type T must bu nothrow_move_constructible");
129 explicit Guard(T &_x)
130 : m_guarded(std::addressof(_x))
131 , m_tmp(std::move(_x))
133 destroy_at(m_guarded);
138 if (unlikely(m_guarded)) {
139 construct_at(m_guarded, std::move(m_tmp));
142 Guard(
const Guard &) =
delete;
143 Guard &operator=(
const Guard &) =
delete;
145 T &&release() noexcept {
return std::move(m_tmp); }
153namespace __dexpected {
156struct _is_dexpected :
public std::false_type
160template <
typename T,
typename E>
161struct _is_dexpected<DExpected<T, E>> :
public std::true_type
166struct _is_dunexpected :
public std::false_type
171struct _is_dunexpected<DUnexpected<T>> :
public std::true_type
176constexpr bool _can_be_dunexpected()
178 return std::is_object<E>::value and !std::is_array<E>::value and !_is_dunexpected<E>() and !std::is_const<E>::value and
179 !std::is_volatile<E>::value;
182template <typename Tp,
185 typename std::enable_if<std::is_nothrow_constructible<Tp, Vp>::value and std::is_nothrow_move_constructible<Tp>::value,
187void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg) noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
190 construct_at(_newVal, std::forward<Vp>(_arg));
193template <
typename Tp,
196 typename std::enable_if<std::is_nothrow_constructible<Tp, Vp>::value and !std::is_nothrow_move_constructible<Tp>::value,
198void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg)
noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
201 construct_at(_newVal, std::forward<Vp>(_arg));
204template <
typename Tp,
207 typename std::enable_if<!std::is_nothrow_constructible<Tp, Vp>::value and std::is_nothrow_move_constructible<Tp>::value,
209void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg)
noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
211 Tp _tmp(std::forward<Vp>(_arg));
213 construct_at(_newVal, std::move(_tmp));
220 typename std::enable_if<!std::is_nothrow_constructible<Tp, Vp>::value and !std::is_nothrow_move_constructible<Tp>::value,
222void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg)
noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
224 __dexpected::Guard<Up> _guard(*_oldVal);
225 construct_at(_newVal, std::forward<Vp>(_arg));
237template <
typename E = DError>
240 static_assert(__dexpected::_can_be_dunexpected<E>(),
"can't be dunexpected");
258 template <
typename Er = E,
259 typename std::enable_if<!std::is_same<typename remove_cvref<Er>::type,
DUnexpected>::value and
260 !std::is_same<typename remove_cvref<Er>::type, emplace_tag>::value and
261 std::is_constructible<E, Er>::value,
263 constexpr explicit DUnexpected(Er &&_e)
noexcept(std::is_nothrow_constructible<E, Er>::value)
264 : m_error(std::forward<Er>(_e))
276 template <
typename... Args>
277 constexpr explicit DUnexpected(emplace_tag, Args &&...args)
noexcept(std::is_nothrow_constructible<E, Args...>::value)
278 : m_error(std::forward<Args>(args)...)
280 static_assert(std::is_constructible<E, Args...>::value,
"can't construct E from args.");
293 template <
typename U,
typename... Args>
294 constexpr explicit DUnexpected(emplace_tag, std::initializer_list<U> _li, Args &&...args)
noexcept(
295 std::is_nothrow_constructible<E, std::initializer_list<U> &, Args...>::value)
296 : m_error(_li, std::forward<Args>(args)...)
314 constexpr const E &
error() const &noexcept {
return m_error; }
320 E &
error() &
noexcept {
return m_error; }
327 constexpr const E &&
error() const &&noexcept {
return std::move(m_error); }
334 E &&
error() &&
noexcept {
return std::move(m_error); }
343 swap(m_error, _other.m_error);
352 template <
typename Er>
355 return _x.m_error == _y.
error();
374template <
typename T,
typename E = DError>
377 template <
typename,
typename>
379 static_assert(!std::is_reference<T>::value,
"type T can't be reference type");
380 static_assert(!std::is_function<T>::value,
"type T can't be function type");
381 static_assert(!std::is_same<typename std::remove_cv<T>::type, dunexpected_tag>::value,
"type T can't be dunexpected_tag");
382 static_assert(!std::is_same<typename std::remove_cv<T>::type, emplace_tag>::value,
"type T can't be emplace_tag");
383 static_assert(!__dexpected::_is_dunexpected<typename std::remove_cv<T>::type>::value,
"type T can't be DUnexpected");
384 static_assert(__dexpected::_can_be_dunexpected<E>(),
"type E can't be dunexpected");
386 template <
typename U,
typename G,
typename Unex = DUnexpected<E>>
387 static constexpr bool __cons_from_DExpected()
389 return std::is_constructible<T, DExpected<U, G> &>::value or std::is_constructible<T, DExpected<U, G>>::value or
390 std::is_constructible<T, const DExpected<U, G>>::value or
391 std::is_constructible<T, const DExpected<U, G> &>::value or std::is_convertible<DExpected<U, G> &, T>::value or
392 std::is_convertible<DExpected<U, G>, T>::value or std::is_convertible<const DExpected<U, G> &, T>::value or
393 std::is_convertible<const DExpected<U, G>, T>::value or std::is_constructible<Unex, DExpected<U, G> &>::value or
394 std::is_constructible<Unex, DExpected<U, G>>::value or
395 std::is_constructible<Unex, const DExpected<U, G> &>::value or
396 std::is_constructible<Unex, const DExpected<U, G>>::value;
399 template <
typename U,
typename G>
400 static constexpr bool __explicit_conv()
402 return !std::is_convertible<U, T>::value or !std::is_convertible<G, E>::value;
405 static constexpr bool des_value()
407 return !std::is_trivially_destructible<T>::value or !std::is_trivially_destructible<E>::value;
410 template <
typename V>
411 void assign_val(V &&_v)
414 m_value = std::forward<V>(_v);
416 __dexpected::reinit(std::addressof(m_value), std::addressof(m_error), std::forward<V>(_v));
421 template <
typename V>
422 void assign_err(V &&_v)
425 __dexpected::reinit(std::addressof(m_error), std::addressof(m_value), std::forward<V>(_v));
428 m_error = std::forward<V>(_v);
432 template <typename Ep = E, typename std::enable_if<std::is_nothrow_move_constructible<Ep>::value,
bool>::type =
true>
433 void swap_val_err(
DExpected &_other)
noexcept(
434 std::is_nothrow_move_constructible<Ep>::value and std::is_nothrow_move_constructible<T>::value)
436 __dexpected::Guard<E> _guard(_other.m_error);
437 construct_at(std::addressof(_other.m_value), std::move(m_value));
438 _other.m_has_value =
true;
439 destroy_at(std::addressof(m_value));
440 construct_at(std::addressof(m_error), _guard.release());
444 template <typename Ep = E, typename std::enable_if<!std::is_nothrow_move_constructible<Ep>::value,
bool>::type =
true>
445 void swap_val_err(
DExpected &_other)
noexcept(
446 std::is_nothrow_move_constructible<Ep>::value and std::is_nothrow_move_constructible<T>::value)
448 __dexpected::Guard<T> _guard(_other.m_value);
449 construct_at(std::addressof(m_error), std::move(_other.m_error));
451 destroy_at(std::addressof(_other.m_error));
452 construct_at(std::addressof(_other.m_value), _guard.release());
453 _other.m_has_value =
true;
457 using value_type = T;
458 using error_type = E;
460 template <
typename U>
466 template <typename std::enable_if<std::is_default_constructible<T>::value,
bool>::type =
true>
467 constexpr DExpected() noexcept(std::is_nothrow_default_constructible<T>::value)
477 typename std::enable_if<std::is_copy_constructible<T>::value and std::is_copy_constructible<E>::value,
bool>::type =
true>
479 std::is_nothrow_copy_constructible<T>::value and std::is_nothrow_copy_constructible<E>::value)
480 : m_has_value(_x.m_has_value)
483 construct_at(std::addressof(m_value), _x.m_value);
485 construct_at(std::addressof(m_error), _x.m_error);
492 typename std::enable_if<std::is_move_constructible<T>::value and std::is_move_constructible<E>::value,
bool>::type =
true>
494 std::is_nothrow_move_constructible<T>::value and std::is_nothrow_move_constructible<E>::value)
495 : m_has_value(_x.m_has_value)
498 construct_at(std::addressof(m_value), std::move(_x).m_value);
500 construct_at(std::addressof(m_error), std::move(_x).m_error);
512 typename std::enable_if<std::is_constructible<T, const U &>::value and std::is_constructible<E, const G &>::value and
513 !__cons_from_DExpected<U, G>() and !__explicit_conv<const U &, const G &>(),
516 std::is_nothrow_constructible<T, const U &>::value and std::is_nothrow_constructible<E, const G &>::value)
517 : m_has_value(_x.m_has_value)
520 construct_at(std::addressof(m_value), _x.m_value);
522 construct_at(std::addressof(m_error), _x.m_error);
535 typename std::enable_if<std::is_constructible<T, const U &>::value and std::is_constructible<E, const G &>::value and
536 !__cons_from_DExpected<U, G>() and __explicit_conv<const U &, const G &>(),
539 std::is_nothrow_constructible<T, const U &>::value and std::is_nothrow_constructible<E, const G &>::value)
540 : m_has_value(_x.m_has_value)
543 construct_at(std::addressof(m_value), _x.m_value);
545 construct_at(std::addressof(m_error), _x.m_error);
555 template <
typename U,
557 typename std::enable_if<std::is_constructible<T, U>::value and std::is_constructible<E, G>::value and
558 !__cons_from_DExpected<U, G>() and !__explicit_conv<U, G>(),
561 std::is_nothrow_constructible<T, U>::value and std::is_nothrow_constructible<E, G>::value)
562 : m_has_value(_x.m_has_value)
565 construct_at(std::addressof(m_value), std::move(_x).m_value);
567 construct_at(std::addressof(m_error), std::move(_x).m_error);
577 template <
typename U,
579 typename std::enable_if<std::is_constructible<T, U>::value and std::is_constructible<E, G>::value and
580 !__cons_from_DExpected<U, G>() and __explicit_conv<U, G>(),
583 std::is_nothrow_constructible<T, U>::value and std::is_nothrow_constructible<E, G>::value)
584 : m_has_value(_x.m_has_value)
587 construct_at(std::addressof(m_value), std::move(_x).m_value);
589 construct_at(std::addressof(m_error), std::move(_x).m_error);
599 template <
typename U = T,
600 typename std::enable_if<!std::is_same<typename remove_cvref<U>::type,
DExpected>::value and
601 !std::is_same<typename remove_cvref<U>::type, emplace_tag>::value and
602 !__dexpected::_is_dunexpected<typename remove_cvref<U>::type>::value and
603 std::is_constructible<T, U>::value and !std::is_convertible<U, T>::value,
605 constexpr explicit DExpected(U &&_v)
noexcept(std::is_nothrow_constructible<T, U>::value)
607 , m_value(std::forward<U>(_v))
619 template <
typename U = T,
620 typename std::enable_if<!std::is_same<typename remove_cvref<U>::type,
DExpected>::value and
621 !std::is_same<typename remove_cvref<U>::type, emplace_tag>::value and
622 !__dexpected::_is_dunexpected<typename remove_cvref<U>::type>::value and
623 std::is_constructible<T, U>::value and std::is_convertible<U, T>::value,
625 constexpr DExpected(U &&_v)
noexcept(std::is_nothrow_constructible<T, U>::value)
627 , m_value(std::forward<U>(_v))
638 template <
typename G = E,
639 typename std::enable_if<std::is_constructible<E, const G &>::value and !std::is_convertible<const G &, E>::value,
643 , m_error(_u.error())
653 template <
typename G = E,
654 typename std::enable_if<std::is_constructible<E, const G &>::value and std::is_convertible<const G &, E>::value,
658 , m_error(_u.error())
671 typename std::enable_if<std::is_constructible<E, G>::value and !std::is_convertible<G, E>::value,
bool>::type =
true>
674 , m_error(std::move(_u).error())
685 template <
typename G = E,
686 typename std::enable_if<std::is_constructible<E, G>::value and std::is_convertible<G, E>::value,
bool>::type =
true>
689 , m_error(std::move(_u).error())
700 template <
typename... Args>
701 constexpr explicit DExpected(emplace_tag, Args &&...args)
noexcept(std::is_nothrow_constructible<T, Args...>::value)
703 , m_value(std::forward<Args>(args)...)
706 static_assert(std::is_constructible<T, Args...>::value,
"can't construct T from args.");
718 template <
typename U,
typename... Args>
719 constexpr explicit DExpected(emplace_tag, std::initializer_list<U> _li, Args &&...args)
noexcept(
720 std::is_nothrow_constructible<T, std::initializer_list<U> &, Args...>::value)
722 , m_value(_li, std::forward<Args>(args)...)
724 static_assert(std::is_constructible<T, std::initializer_list<U> &, Args...>::value,
"can't construct T from args.");
734 template <
typename... Args>
735 constexpr explicit DExpected(dunexpected_tag, Args &&...args)
noexcept(std::is_nothrow_constructible<E, Args...>::value)
737 , m_error(std::forward<Args>(args)...)
740 static_assert(std::is_constructible<E, Args...>::value,
"can't construct E from args.");
752 template <
typename U,
typename... Args>
753 constexpr explicit DExpected(dunexpected_tag, std::initializer_list<U> _li, Args &&...args)
noexcept(
754 std::is_nothrow_constructible<E, std::initializer_list<U> &, Args...>::value)
756 , m_error(_li, std::forward<Args>(args)...)
758 static_assert(std::is_constructible<E, std::initializer_list<U> &, Args...>::value,
"can't construct E from args.");
768 destroy_at(std::addressof(m_value));
770 destroy_at(std::addressof(m_error));
784 template <typename std::enable_if<std::is_copy_assignable<T>::value and std::is_copy_constructible<T>::value and
785 std::is_copy_assignable<E>::value and std::is_copy_constructible<E>::value and
786 (std::is_nothrow_move_constructible<T>::value or
787 std::is_nothrow_move_constructible<E>::value),
790 std::is_nothrow_copy_constructible<T>::value and std::is_nothrow_copy_constructible<E>::value
791 and std::is_nothrow_copy_assignable<T>::value and std::is_nothrow_copy_assignable<E>::value)
794 this->assign_val(_x.m_value);
796 this->assign_err(_x.m_error);
805 template <typename std::enable_if<std::is_move_assignable<T>::value and std::is_move_constructible<T>::value and
806 std::is_move_assignable<E>::value and std::is_move_constructible<E>::value and
807 (std::is_nothrow_move_constructible<T>::value or
808 std::is_nothrow_move_constructible<E>::value),
811 std::is_nothrow_move_constructible<T>::value and std::is_nothrow_move_constructible<E>::value
812 and std::is_nothrow_move_assignable<T>::value and std::is_nothrow_move_assignable<E>::value)
815 assign_val(std::move(_x.m_value));
817 assign_err(std::move(_x.m_error));
828 typename std::enable_if<!std::is_same<DExpected, typename remove_cvref<U>::type>::value and
829 !__dexpected::_is_dunexpected<typename remove_cvref<U>::type>::value and
830 std::is_constructible<T, U>::value and std::is_assignable<T &, U>::value and
831 (std::is_nothrow_constructible<T, U>::value or std::is_nothrow_move_constructible<T>::value or
832 std::is_nothrow_move_constructible<E>::value),
836 assign_val(std::forward<U>(_v));
845 template <
typename G,
846 typename std::enable_if<std::is_constructible<E, const G &>::value and std::is_assignable<E &, const G &>::value and
847 (std::is_nothrow_constructible<E, const G &>::value or
848 std::is_nothrow_move_constructible<T>::value or std::is_move_constructible<E>::value),
852 assign_err(_e.
error());
862 template <
typename G,
863 typename std::enable_if<std::is_constructible<E, G>::value and std::is_assignable<E &, G>::value and
864 (std::is_nothrow_constructible<E, G>::value or
865 std::is_nothrow_move_constructible<T>::value or std::is_move_constructible<E>::value),
869 assign_err(std::move(_e).error());
879 template <
typename... Args>
882 static_assert(std::is_nothrow_constructible<T, Args...>::value,
"type T should have nothrow_constructible");
884 destroy_at(std::addressof(m_value));
886 destroy_at(std::addressof(m_error));
889 construct_at(std::addressof(m_value), std::forward<Args>(args)...);
901 template <
typename U,
typename... Args>
902 T &
emplace(std::initializer_list<U> li, Args &&...args)
noexcept
904 static_assert(std::is_nothrow_constructible<T, std::initializer_list<U> &, Args...>::value,
905 "type T should have a noexcept constructor");
907 destroy_at(std::addressof(m_value));
909 destroy_at(std::addressof(m_error));
911 construct_at(std::addressof(m_value), li, std::forward<Args>(args)...);
920 template <typename std::enable_if<std::is_move_constructible<T>::value and std::is_move_constructible<E>::value and
921 (std::is_nothrow_move_constructible<T>::value or
922 std::is_nothrow_move_constructible<E>::value),
925 swap(
DExpected &_x)
noexcept(std::is_nothrow_move_constructible<T>::value and std::is_nothrow_move_constructible<E>::value)
928 if (_x.m_has_value) {
930 swap(m_value, _x.m_value);
932 this->swap_val_err(_x);
936 _x.swap_val_err(*
this);
939 swap(m_error, _x.m_error);
951 return std::addressof(m_value);
961 return std::addressof(m_value);
991 return std::move(m_value);
1000 assert(m_has_value);
1001 return std::move(m_value);
1008 constexpr explicit operator bool() const noexcept {
return m_has_value; }
1014 constexpr bool hasValue() const noexcept {
return m_has_value; }
1022 if (likely(m_has_value)) {
1034 if (likely(m_has_value)) {
1047 if (likely(m_has_value)) {
1048 return std::move(m_value);
1060 if (likely(m_has_value)) {
1061 return std::move(m_value);
1072 assert(!m_has_value);
1082 assert(!m_has_value);
1093 assert(!m_has_value);
1094 return std::move(m_error);
1104 assert(!m_has_value);
1105 return std::move(m_error);
1115 template <
typename U>
1118 static_assert(std::is_copy_constructible<T>::value,
"type T should have an copy constructor.");
1119 static_assert(std::is_convertible<U, T>::value,
"type U must can be converted to T.");
1122 return static_cast<T
>(std::forward<U>(_v));
1132 template <
typename U>
1135 static_assert(std::is_move_constructible<T>::value,
"type T must bu copy_constructible.");
1136 static_assert(std::is_convertible<U, T>::value,
"type U must can be converted to T.");
1138 return std::move(m_value);
1139 return static_cast<T
>(std::forward<U>(_v));
1145 template <typename U, typename E2, typename std::enable_if<!std::is_void<U>::value,
bool>::type =
true>
1148 const DExpected<U, E2> &_y)
noexcept(
noexcept(bool(*_x == *_y)) and
noexcept(
bool(_x.error() == _y.error())))
1151 return _y.hasValue() and bool(*_x == *_y);
1153 return !_y.hasValue() and bool(_x.error() == _x.error());
1159 template <
typename U>
1162 return _x.hasValue() && bool(*_x == _v);
1168 template <
typename E2>
1170 const DUnexpected<E2> &_e)
noexcept(
noexcept(bool(_x.error() == _e.error())))
1172 return !_x.hasValue() && bool(_x.error() == _e.error());
1193template <
typename E>
1196 static_assert(__dexpected::_can_be_dunexpected<E>(),
"type E can't be DUnexpected.");
1197 static constexpr bool des_value() {
return !std::is_trivially_destructible<E>::value; }
1199 template <
typename,
typename>
1202 template <
typename U,
typename G,
typename Unex = DUnexpected<E>>
1203 static constexpr bool __cons_from_DExpected()
1205 return std::is_constructible<Unex, DExpected<U, G> &>::value and std::is_constructible<Unex, DExpected<U, G>>::value and
1206 std::is_constructible<Unex, const DExpected<U, G> &>::value and
1207 std::is_constructible<Unex, const DExpected<U, G>>::value;
1210 template <
typename V>
1211 void assign_err(V &&_v)
1214 construct_at(std::addressof(m_error), std::forward<V>(_v));
1215 m_has_value =
false;
1217 m_error = std::forward<V>(_v);
1222 using value_type = void;
1223 using error_type = E;
1225 template <
typename U>
1234 template <typename std::enable_if<std::is_copy_constructible<E>::value,
bool>::type =
true>
1235 DExpected(
const DExpected &_x)
noexcept(std::is_nothrow_copy_constructible<E>::value)
1236 : m_has_value(_x.m_has_value)
1240 construct_at(std::addressof(m_error), _x.m_error);
1243 template <typename std::enable_if<std::is_move_constructible<E>::value,
bool>::type =
true>
1245 : m_has_value(_x.m_has_value)
1249 construct_at(std::addressof(m_error), std::move(_x).m_error);
1252 template <
typename U,
1254 typename std::enable_if<std::is_void<U>::value and std::is_constructible<E, const G &>::value and
1255 !__cons_from_DExpected<U, G>() and !std::is_convertible<const G &, E>::value,
1258 : m_has_value(_x.m_has_value)
1262 construct_at(std::addressof(m_error), _x.m_error);
1265 template <
typename U,
1267 typename std::enable_if<std::is_void<U>::value and std::is_constructible<E, const G &>::value and
1268 !__cons_from_DExpected<U, G>() and std::is_convertible<const G &, E>::value,
1271 : m_has_value(_x.m_has_value)
1275 construct_at(std::addressof(m_error), _x.m_error);
1278 template <
typename U,
1280 typename std::enable_if<std::is_void<U>::value and std::is_constructible<E, G>::value and
1281 __cons_from_DExpected<U, G>() and !std::is_convertible<G, E>::value,
1284 : m_has_value(_x.m_has_value)
1288 construct_at(std::addressof(m_error), std::move(_x).m_error);
1291 template <
typename U,
1293 typename std::enable_if<std::is_void<U>::value and std::is_constructible<E, G>::value and
1294 __cons_from_DExpected<U, G>() and std::is_convertible<G, E>::value,
1297 : m_has_value(_x.m_has_value)
1301 construct_at(std::addressof(m_error), std::move(_x).m_error);
1304 template <
typename G = E,
1305 typename std::enable_if<std::is_constructible<E, const G &>::value and !std::is_convertible<const G &, E>::value,
1307 constexpr explicit DExpected(
const DUnexpected<G> &_u)
noexcept(std::is_nothrow_constructible<E, const G &>::value)
1308 : m_has_value(
false)
1309 , m_error(_u.
error())
1313 template <
typename G = E,
1314 typename std::enable_if<std::is_constructible<E, const G &>::value and std::is_convertible<const G &, E>::value,
1317 : m_has_value(
false)
1318 , m_error(_u.
error())
1324 typename std::enable_if<std::is_constructible<E, G>::value and !std::is_convertible<G, E>::value,
bool>::type =
true>
1326 : m_has_value(
false)
1327 , m_error(std::move(_u).error())
1331 template <
typename G = E,
1332 typename std::enable_if<std::is_constructible<E, G>::value and std::is_convertible<G, E>::value,
bool>::type =
true>
1334 : m_has_value(
false)
1335 , m_error(std::move(_u).error())
1339 template <
typename... Args>
1340 constexpr explicit DExpected(emplace_tag) noexcept
1345 template <
typename... Args>
1346 constexpr explicit DExpected(dunexpected_tag, Args &&...args)
noexcept(std::is_nothrow_constructible<E, Args...>::value)
1347 : m_has_value(
false)
1348 , m_error(std::forward<Args>(args)...)
1350 static_assert(std::is_constructible<E, Args...>::value,
"type E can't construct from args");
1353 template <
typename U,
typename... Args>
1354 constexpr explicit DExpected(dunexpected_tag,
1355 std::initializer_list<U> _li,
1356 Args &&...args)
noexcept(std::is_nothrow_constructible<E, Args...>::value)
1357 : m_has_value(
false)
1358 , m_error(_li, std::forward<Args>(args)...)
1360 static_assert(std::is_constructible<E, std::initializer_list<U> &, Args...>::value,
"type E can't construct from args");
1365 if (des_value() and !m_has_value) {
1366 destroy_at(std::addressof(m_error));
1373 typename std::enable_if<std::is_copy_constructible<E>::value and std::is_copy_assignable<E>::value,
bool>::type =
true>
1375 std::is_nothrow_copy_constructible<E>::value and std::is_nothrow_copy_assignable<E>::value)
1380 assign_err(_x.m_error);
1385 typename std::enable_if<std::is_move_constructible<E>::value and std::is_move_assignable<E>::value,
bool>::type =
true>
1387 operator=(
DExpected &&_x)
noexcept(std::is_nothrow_move_constructible<E>::value and std::is_nothrow_move_assignable<E>::value)
1392 assign_err(std::move(_x.m_error));
1396 template <
typename G,
1397 typename std::enable_if<std::is_constructible<E, const G &>::value and std::is_assignable<E &, const G &>::value,
1401 assign_err(_e.
error());
1407 typename std::enable_if<std::is_constructible<E, G>::value and std::is_assignable<E &, G>::value,
bool>::type =
true>
1410 assign_err(std::move(_e.
error()));
1414 void emplace()
noexcept
1417 destroy_at(std::addressof(m_error));
1422 template <typename std::enable_if<std::is_move_constructible<E>::value,
bool>::type =
true>
1423 void swap(
DExpected &_x)
noexcept(std::is_nothrow_move_constructible<E>::value)
1426 if (!_x.m_has_value) {
1427 construct_at(std::addressof(m_error), std::move(_x.m_error));
1428 destroy_at(std::addressof(_x.m_error));
1429 m_has_value =
false;
1430 _x.m_has_value =
true;
1433 if (_x.m_has_value) {
1434 construct_at(std::addressof(_x.m_error), std::move(m_error));
1435 destroy_at(std::addressof(m_error));
1437 _x.m_has_value =
false;
1440 swap(m_error, _x.m_error);
1445 constexpr explicit operator bool()
const noexcept {
return m_has_value; }
1447 constexpr bool hasValue()
const noexcept {
return m_has_value; }
1449 void operator*()
const noexcept { assert(m_has_value); }
1451 void value()
const &
1453 if (likely(m_has_value))
1460 if (likely(m_has_value))
1465 const E &error()
const &
noexcept
1467 assert(!m_has_value);
1471 E &error() &
noexcept
1473 assert(!m_has_value);
1477 const E &&error()
const &&
noexcept
1479 assert(!m_has_value);
1480 return std::move(m_error);
1483 E &&error() &&
noexcept
1485 assert(!m_has_value);
1486 return std::move(m_error);
1489 template <typename U, typename E2, typename std::enable_if<std::is_void<U>::value,
bool>::type =
true>
1498 template <
typename E2>
模板类Dtk::Core::DExpected提供存储两个值之一的方式。Dtk::Core::DExpected的对象要么保有一个期待的T类型值,要么保有一个不期待的E类型值,不会没有值。
Definition dexpected.h:376
constexpr DExpected(emplace_tag, Args &&...args) noexcept(std::is_nothrow_constructible< T, Args... >::value)
Dtk::Core::DExpected的转发构造函数,从参数直接构造出期待值
Definition dexpected.h:701
T value_or(U &&_v) const &
如果有期待值返回期待值,否则返回传入的默认值
Definition dexpected.h:1116
const T & operator*() const &noexcept
重载解引用运算符
Definition dexpected.h:968
DExpected(const DExpected &_x) noexcept(std::is_nothrow_copy_constructible< T >::value and std::is_nothrow_copy_constructible< E >::value)
Dtk::Core::DExpected的拷贝构造函数
Definition dexpected.h:478
constexpr DExpected(emplace_tag, std::initializer_list< U > _li, Args &&...args) noexcept(std::is_nothrow_constructible< T, std::initializer_list< U > &, Args... >::value)
Dtk::Core::DExpected的转发构造函数,从参数直接构造出期待值
Definition dexpected.h:719
T * operator->() noexcept
重载箭头运算符
Definition dexpected.h:958
constexpr DExpected(DUnexpected< G > &&_u) noexcept(std::is_nothrow_constructible< E, G >::value)
Dtk::Core::DExpected的移动构造函数,从Dtk::Core::DUnexpected构造出Dtk::Core::DExpected对象
Definition dexpected.h:672
DExpected & operator=(DExpected &&_x) noexcept(std::is_nothrow_move_constructible< T >::value and std::is_nothrow_move_constructible< E >::value and std::is_nothrow_move_assignable< T >::value and std::is_nothrow_move_assignable< E >::value)
Dtk::Core::DExpected的移动赋值运算符
Definition dexpected.h:810
friend constexpr bool operator==(const DExpected &_x, const U &_v) noexcept(noexcept(bool(*_x==_v)))
重载相等运算符
Definition dexpected.h:1160
T value_or(U &&_v) &&
如果有期待值返回期待值,否则返回传入的默认值
Definition dexpected.h:1133
T & emplace(std::initializer_list< U > li, Args &&...args) noexcept
从参数直接转发构造期待值
Definition dexpected.h:902
DExpected(DExpected &&_x) noexcept(std::is_nothrow_move_constructible< T >::value and std::is_nothrow_move_constructible< E >::value)
Dtk::Core::DExpected的移动构造函数
Definition dexpected.h:493
constexpr DExpected(dunexpected_tag, std::initializer_list< U > _li, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U > &, Args... >::value)
Dtk::Core::DExpected的转发构造函数,从参数直接构造出不期待值
Definition dexpected.h:753
DExpected & operator=(const DUnexpected< G > &_e)
Dtk::Core::DExpected的拷贝赋值运算符
Definition dexpected.h:850
const T * operator->() const noexcept
重载箭头运算符
Definition dexpected.h:948
const E && error() const &&noexcept
获取Dtk::Core::DExpected的不期待值
Definition dexpected.h:1091
T & value() &
获取Dtk::Core::DExpected的期待值
Definition dexpected.h:1032
T && operator*() &&noexcept
重载解引用运算符
Definition dexpected.h:998
T && value() &&
获取Dtk::Core::DExpected的期待值
Definition dexpected.h:1058
constexpr DExpected() noexcept(std::is_nothrow_default_constructible< T >::value)
Dtk::Core::DExpected的默认构造函数
Definition dexpected.h:467
E & error() &noexcept
获取Dtk::Core::DExpected的不期待值
Definition dexpected.h:1080
DExpected & operator=(const DExpected &_x) noexcept(std::is_nothrow_copy_constructible< T >::value and std::is_nothrow_copy_constructible< E >::value and std::is_nothrow_copy_assignable< T >::value and std::is_nothrow_copy_assignable< E >::value)
Dtk::Core::DExpected的拷贝赋值运算符
Definition dexpected.h:789
E && error() &&noexcept
获取Dtk::Core::DExpected的不期待值
Definition dexpected.h:1102
const E & error() const &noexcept
获取Dtk::Core::DExpected的不期待值
Definition dexpected.h:1070
constexpr DExpected(dunexpected_tag, Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
Dtk::Core::DExpected的转发构造函数,从参数直接构造出不期待值
Definition dexpected.h:735
constexpr DExpected(U &&_v) noexcept(std::is_nothrow_constructible< T, U >::value)
Dtk::Core::DExpected的移动构造函数,直接从期待类型构造出Dtk::Core::DExpected对象
Definition dexpected.h:605
~DExpected()
Dtk::Core::DExpected的析构函数
Definition dexpected.h:764
friend bool operator==(const DExpected &_x, const DExpected< U, E2 > &_y) noexcept(noexcept(bool(*_x== *_y)) and noexcept(bool(_x.error()==_y.error())))
重载相等运算符
Definition dexpected.h:1147
friend constexpr bool operator==(const DExpected &_x, const DUnexpected< E2 > &_e) noexcept(noexcept(bool(_x.error()==_e.error())))
重载相等运算符
Definition dexpected.h:1169
const T & value() const &
获取Dtk::Core::DExpected的期待值
Definition dexpected.h:1020
void swap(DExpected &_x) noexcept(std::is_nothrow_move_constructible< T >::value and std::is_nothrow_move_constructible< E >::value)
交换两个Dtk::Core::DExpected的值
Definition dexpected.h:925
DExpected & operator=(const DExpected &)=delete
Dtk::Core::DExpected的默认拷贝赋值运算符
constexpr bool hasValue() const noexcept
判断Dtk::Core::DExpected是否有值
Definition dexpected.h:1014
constexpr DExpected(const DUnexpected< G > &_u) noexcept(std::is_nothrow_constructible< E, const G & >::value)
Dtk::Core::DExpected的拷贝构造函数,从Dtk::Core::DUnexpected构造出Dtk::Core::DExpected对象
Definition dexpected.h:641
T & emplace(Args &&...args) noexcept
从参数直接转发构造期待值
Definition dexpected.h:880
const T && value() const &&
获取Dtk::Core::DExpected的期待值
Definition dexpected.h:1045
DExpected & operator=(DUnexpected< G > &&_e)
Dtk::Core::DExpected的移动赋值运算符
Definition dexpected.h:867
DExpected & operator=(U &&_v)
Dtk::Core::DExpected的转发赋值运算符
Definition dexpected.h:834
const T && operator*() const &&noexcept
重载解引用运算符
Definition dexpected.h:988
T & operator*() &noexcept
重载解引用运算符
Definition dexpected.h:978
friend void swap(DExpected &_x, DExpected &_y) noexcept(noexcept(_x.swap(_y)))
交换两个Dtk::Core::DExpected中的值
Definition dexpected.h:1178
类模板Dtk::Core::DUnexpected代表一个Dtk::Core::DExpected中存储的不期待的值
Definition dexpected.h:239
constexpr DUnexpected(emplace_tag, Args &&...args) noexcept(std::is_nothrow_constructible< E, Args... >::value)
直接从参数构造出一个包含错误类型为E的对象的Dtk::Core::DUnexpected对象
Definition dexpected.h:277
constexpr DUnexpected(DUnexpected &&)=default
Dtk::Core::DUnexpected的默认移动构造函数
DUnexpected & operator=(const DUnexpected &)=default
Dtk::Core::DUnexpected的默认拷贝赋值运算符
E && error() &&noexcept
获取Dtk::Core::DUnexpected持有的不期待值
Definition dexpected.h:334
constexpr const E && error() const &&noexcept
获取Dtk::Core::DUnexpected持有的不期待值
Definition dexpected.h:327
constexpr DUnexpected(Er &&_e) noexcept(std::is_nothrow_constructible< E, Er >::value)
使用类型E直接初始化一个Dtk::Core::DUnexpected对象
Definition dexpected.h:263
constexpr const E & error() const &noexcept
获取Dtk::Core::DUnexpected持有的不期待值
Definition dexpected.h:314
constexpr DUnexpected(emplace_tag, std::initializer_list< U > _li, Args &&...args) noexcept(std::is_nothrow_constructible< E, std::initializer_list< U > &, Args... >::value)
从参数和初始化列表构造出一个包含错误类型为E的对象的Dtk::Core::DUnexpected对象
Definition dexpected.h:294
constexpr DUnexpected(const DUnexpected &)=default
Dtk::Core::DUnexpected的默认拷贝构造函数
void swap(DUnexpected &_other)
交换两个Dtk::Core::DUnexpected的值
Definition dexpected.h:340
DUnexpected & operator=(DUnexpected &&)=default
Dtk::Core::DUnexpected的默认移动赋值运算符
E & error() &noexcept
获取Dtk::Core::DUnexpected持有的不期待值
Definition dexpected.h:320
friend void swap(DUnexpected &_x, DUnexpected &_y)
交换两个Dtk::Core::DUnexpected的值
Definition dexpected.h:361
friend constexpr bool operator==(const DUnexpected &_x, const DUnexpected< Er > _y)
重载相等运算符
Definition dexpected.h:353
Definition dexpected.h:73
Definition dexpected.h:49