DtkCore
DTK Core module
载入中...
搜索中...
未找到
dexpected.h
1// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
5#ifndef DEXPECTED_H
6#define DEXPECTED_H
7
8#include <cassert>
9#include <cstdlib>
10#include <exception>
11#include <initializer_list>
12#include <memory>
13#include <type_traits>
14
15#include "derror.h"
16
17DCORE_BEGIN_NAMESPACE
18
19#define likely(x) __builtin_expect(static_cast<long int>((x)), 1)
20#define unlikely(x) __builtin_expect(reinterpret_cast<long int>((x)), 0)
21
22#if __cpp_exceptions
23#define _DEXPECTED_THROW_OR_ABORT(_EXC) (throw(_EXC))
24#else
25#define _DEXPECTED_THROW_OR_ABORT(_EXC) (std::abort())
26#endif
27
28template <typename T, typename E>
29class DExpected;
30
31template <typename E>
32class DUnexpected;
33
34template <bool v>
35using _bool_constant = std::integral_constant<bool, v>;
36
40enum class emplace_tag { USE_EMPLACE };
41
45enum class dunexpected_tag { DUNEXPECTED };
46
47template <typename Type>
49{
50 using type = typename std::remove_cv<typename std::remove_reference<Type>::type>::type;
51};
52
53template <typename E>
55
56template <>
57class bad_result_access<void> : public std::exception
58{
59protected:
60 bad_result_access() noexcept {}
61 bad_result_access(const bad_result_access &) = default;
63 bad_result_access &operator=(const bad_result_access &) = default;
64 bad_result_access &operator=(bad_result_access &&) = default;
65 ~bad_result_access() = default;
66
67public:
68 const char *what() const noexcept override { return "bad access to DExpected without value"; }
69};
70
71template <typename E>
73{
74public:
75 explicit bad_result_access(E _e)
76 : m_error(std::move(_e))
77 {
78 }
79
80 E &error() &noexcept { return m_error; }
81 const E &error() const &noexcept { return m_error; }
82
83 E error() &&noexcept { return std::move(m_error); }
84 const E error() const &&noexcept { return std::move(m_error); }
85
86private:
87 E m_error;
88};
89
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>()...))
93{
94 return ::new ((void *)p) Type(std::forward<Args>(args)...);
95}
96
97namespace __dexpected {
98template <typename ObjType>
99void destroy_at_obj(ObjType *p)
100{
101 p->~ObjType();
102}
103
104template <typename ArrType>
105void destroy_at_arr(ArrType *p)
106{
107 for (auto &elem : *p)
108 destroy_at_obj(std::addressof(elem));
109}
110} // namespace __dexpected
111
112template <typename Type, typename std::enable_if<std::is_array<Type>::value, bool>::type = true>
113void destroy_at(Type *p)
114{
115 __dexpected::destroy_at_arr(p);
116}
117
118template <typename Type, typename std::enable_if<!std::is_array<Type>::value, bool>::type = true>
119void destroy_at(Type *p)
120{
121 __dexpected::destroy_at_obj(p);
122}
123
124namespace __dexpected {
125template <typename T>
126struct Guard
127{
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))
132 {
133 destroy_at(m_guarded);
134 }
135
136 ~Guard()
137 {
138 if (unlikely(m_guarded)) {
139 construct_at(m_guarded, std::move(m_tmp));
140 }
141 }
142 Guard(const Guard &) = delete;
143 Guard &operator=(const Guard &) = delete;
144
145 T &&release() noexcept { return std::move(m_tmp); }
146
147private:
148 T *m_guarded;
149 T m_tmp;
150};
151} // namespace __dexpected
152
153namespace __dexpected {
154
155template <typename T>
156struct _is_dexpected : public std::false_type
157{
158};
159
160template <typename T, typename E>
161struct _is_dexpected<DExpected<T, E>> : public std::true_type
162{
163};
164
165template <typename T>
166struct _is_dunexpected : public std::false_type
167{
168};
169
170template <typename T>
171struct _is_dunexpected<DUnexpected<T>> : public std::true_type
172{
173};
174
175template <typename E>
176constexpr bool _can_be_dunexpected()
177{
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;
180}
181
182template <typename Tp,
183 typename Up,
184 typename Vp,
185 typename std::enable_if<std::is_nothrow_constructible<Tp, Vp>::value and std::is_nothrow_move_constructible<Tp>::value,
186 bool>::type = true>
187void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg) noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
188{
189 destroy_at(_oldVal);
190 construct_at(_newVal, std::forward<Vp>(_arg));
191}
192
193template <typename Tp,
194 typename Up,
195 typename Vp,
196 typename std::enable_if<std::is_nothrow_constructible<Tp, Vp>::value and !std::is_nothrow_move_constructible<Tp>::value,
197 bool>::type = true>
198void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg) noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
199{
200 destroy_at(_oldVal);
201 construct_at(_newVal, std::forward<Vp>(_arg));
202}
203
204template <typename Tp,
205 typename Up,
206 typename Vp,
207 typename std::enable_if<!std::is_nothrow_constructible<Tp, Vp>::value and std::is_nothrow_move_constructible<Tp>::value,
208 bool>::type = true>
209void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg) noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
210{
211 Tp _tmp(std::forward<Vp>(_arg));
212 destroy_at(_oldVal);
213 construct_at(_newVal, std::move(_tmp));
214}
215
216template <
217 typename Tp,
218 typename Up,
219 typename Vp,
220 typename std::enable_if<!std::is_nothrow_constructible<Tp, Vp>::value and !std::is_nothrow_move_constructible<Tp>::value,
221 bool>::type = true>
222void reinit(Tp *_newVal, Up *_oldVal, Vp &&_arg) noexcept(std::is_nothrow_constructible<Tp, Vp>::value)
223{
224 __dexpected::Guard<Up> _guard(*_oldVal);
225 construct_at(_newVal, std::forward<Vp>(_arg));
226 _guard.release();
227}
228
229} // namespace __dexpected
230
237template <typename E = DError>
239{
240 static_assert(__dexpected::_can_be_dunexpected<E>(), "can't be dunexpected");
241
242public:
246 constexpr DUnexpected(const DUnexpected &) = default;
247
251 constexpr DUnexpected(DUnexpected &&) = default;
252
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,
262 bool>::type = true>
263 constexpr explicit DUnexpected(Er &&_e) noexcept(std::is_nothrow_constructible<E, Er>::value)
264 : m_error(std::forward<Er>(_e))
265 {
266 }
267
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)...)
279 {
280 static_assert(std::is_constructible<E, Args...>::value, "can't construct E from args.");
281 }
282
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)...)
297 {
298 }
299
303 DUnexpected &operator=(const DUnexpected &) = default;
304
309
314 constexpr const E &error() const &noexcept { return m_error; }
315
320 E &error() &noexcept { return m_error; }
321
327 constexpr const E &&error() const &&noexcept { return std::move(m_error); }
328
334 E &&error() &&noexcept { return std::move(m_error); }
335
340 void swap(DUnexpected &_other)
341 {
342 using std::swap;
343 swap(m_error, _other.m_error);
344 }
345
352 template <typename Er>
353 friend constexpr bool operator==(const DUnexpected &_x, const DUnexpected<Er> _y)
354 {
355 return _x.m_error == _y.error();
356 }
357
361 friend void swap(DUnexpected &_x, DUnexpected &_y) { _x.swap(_y); }
362
363private:
364 E m_error;
365};
366
374template <typename T, typename E = DError>
376{
377 template <typename, typename>
378 friend class DExpected;
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");
385
386 template <typename U, typename G, typename Unex = DUnexpected<E>>
387 static constexpr bool __cons_from_DExpected()
388 {
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;
397 }
398
399 template <typename U, typename G>
400 static constexpr bool __explicit_conv()
401 {
402 return !std::is_convertible<U, T>::value or !std::is_convertible<G, E>::value;
403 }
404
405 static constexpr bool des_value()
406 {
407 return !std::is_trivially_destructible<T>::value or !std::is_trivially_destructible<E>::value;
408 }
409
410 template <typename V>
411 void assign_val(V &&_v)
412 {
413 if (m_has_value) {
414 m_value = std::forward<V>(_v);
415 } else {
416 __dexpected::reinit(std::addressof(m_value), std::addressof(m_error), std::forward<V>(_v));
417 m_has_value = true;
418 }
419 }
420
421 template <typename V>
422 void assign_err(V &&_v)
423 {
424 if (m_has_value) {
425 __dexpected::reinit(std::addressof(m_error), std::addressof(m_value), std::forward<V>(_v));
426 m_has_value = false;
427 } else {
428 m_error = std::forward<V>(_v);
429 }
430 }
431
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)
435 {
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());
441 m_has_value = false;
442 }
443
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)
447 {
448 __dexpected::Guard<T> _guard(_other.m_value);
449 construct_at(std::addressof(m_error), std::move(_other.m_error));
450 m_has_value = false;
451 destroy_at(std::addressof(_other.m_error));
452 construct_at(std::addressof(_other.m_value), _guard.release());
453 _other.m_has_value = true;
454 }
455
456public:
457 using value_type = T;
458 using error_type = E;
460 template <typename U>
462
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)
468 : m_has_value(true)
469 , m_value()
470 {
471 }
472
476 template <
477 typename std::enable_if<std::is_copy_constructible<T>::value and std::is_copy_constructible<E>::value, bool>::type = true>
478 DExpected(const DExpected &_x) noexcept(
479 std::is_nothrow_copy_constructible<T>::value and std::is_nothrow_copy_constructible<E>::value)
480 : m_has_value(_x.m_has_value)
481 {
482 if (m_has_value)
483 construct_at(std::addressof(m_value), _x.m_value);
484 else
485 construct_at(std::addressof(m_error), _x.m_error);
486 }
487
491 template <
492 typename std::enable_if<std::is_move_constructible<T>::value and std::is_move_constructible<E>::value, bool>::type = true>
493 DExpected(DExpected &&_x) noexcept(
494 std::is_nothrow_move_constructible<T>::value and std::is_nothrow_move_constructible<E>::value)
495 : m_has_value(_x.m_has_value)
496 {
497 if (m_has_value)
498 construct_at(std::addressof(m_value), std::move(_x).m_value);
499 else
500 construct_at(std::addressof(m_error), std::move(_x).m_error);
501 }
502
509 template <
510 typename U,
511 typename G,
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 &>(),
514 bool>::type = true>
515 DExpected(const DExpected<U, G> &_x) noexcept(
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)
518 {
519 if (m_has_value)
520 construct_at(std::addressof(m_value), _x.m_value);
521 else
522 construct_at(std::addressof(m_error), _x.m_error);
523 }
524
532 template <
533 typename U,
534 typename G,
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 &>(),
537 bool>::type = true>
538 explicit DExpected(const DExpected<U, G> &_x) noexcept(
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)
541 {
542 if (m_has_value)
543 construct_at(std::addressof(m_value), _x.m_value);
544 else
545 construct_at(std::addressof(m_error), _x.m_error);
546 }
547
555 template <typename U,
556 typename G,
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>(),
559 bool>::type = true>
560 DExpected(DExpected<U, G> &&_x) noexcept(
561 std::is_nothrow_constructible<T, U>::value and std::is_nothrow_constructible<E, G>::value)
562 : m_has_value(_x.m_has_value)
563 {
564 if (m_has_value)
565 construct_at(std::addressof(m_value), std::move(_x).m_value);
566 else
567 construct_at(std::addressof(m_error), std::move(_x).m_error);
568 }
569
577 template <typename U,
578 typename G,
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>(),
581 bool>::type = true>
582 explicit DExpected(DExpected<U, G> &&_x) noexcept(
583 std::is_nothrow_constructible<T, U>::value and std::is_nothrow_constructible<E, G>::value)
584 : m_has_value(_x.m_has_value)
585 {
586 if (m_has_value)
587 construct_at(std::addressof(m_value), std::move(_x).m_value);
588 else
589 construct_at(std::addressof(m_error), std::move(_x).m_error);
590 }
591
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,
604 bool>::type = true>
605 constexpr explicit DExpected(U &&_v) noexcept(std::is_nothrow_constructible<T, U>::value)
606 : m_has_value(true)
607 , m_value(std::forward<U>(_v))
608
609 {
610 }
611
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,
624 bool>::type = true>
625 constexpr DExpected(U &&_v) noexcept(std::is_nothrow_constructible<T, U>::value)
626 : m_has_value(true)
627 , m_value(std::forward<U>(_v))
628 {
629 }
630
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,
640 bool>::type = true>
641 constexpr explicit DExpected(const DUnexpected<G> &_u) noexcept(std::is_nothrow_constructible<E, const G &>::value)
642 : m_has_value(false)
643 , m_error(_u.error())
644 {
645 }
646
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,
655 bool>::type = true>
656 constexpr DExpected(const DUnexpected<G> &_u) noexcept(std::is_nothrow_constructible<E, const G &>::value)
657 : m_has_value(false)
658 , m_error(_u.error())
659 {
660 }
661
669 template <
670 typename G = E,
671 typename std::enable_if<std::is_constructible<E, G>::value and !std::is_convertible<G, E>::value, bool>::type = true>
672 constexpr explicit DExpected(DUnexpected<G> &&_u) noexcept(std::is_nothrow_constructible<E, G>::value)
673 : m_has_value(false)
674 , m_error(std::move(_u).error())
675 {
676 }
677
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>
687 constexpr DExpected(DUnexpected<G> &&_u) noexcept(std::is_nothrow_constructible<E, G>::value)
688 : m_has_value(false)
689 , m_error(std::move(_u).error())
690 {
691 }
692
700 template <typename... Args>
701 constexpr explicit DExpected(emplace_tag, Args &&...args) noexcept(std::is_nothrow_constructible<T, Args...>::value)
702 : m_has_value(true)
703 , m_value(std::forward<Args>(args)...)
704
705 {
706 static_assert(std::is_constructible<T, Args...>::value, "can't construct T from args.");
707 }
708
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)
721 : m_has_value(true)
722 , m_value(_li, std::forward<Args>(args)...)
723 {
724 static_assert(std::is_constructible<T, std::initializer_list<U> &, Args...>::value, "can't construct T from args.");
725 }
726
734 template <typename... Args>
735 constexpr explicit DExpected(dunexpected_tag, Args &&...args) noexcept(std::is_nothrow_constructible<E, Args...>::value)
736 : m_has_value(false)
737 , m_error(std::forward<Args>(args)...)
738
739 {
740 static_assert(std::is_constructible<E, Args...>::value, "can't construct E from args.");
741 }
742
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)
755 : m_has_value(false)
756 , m_error(_li, std::forward<Args>(args)...)
757 {
758 static_assert(std::is_constructible<E, std::initializer_list<U> &, Args...>::value, "can't construct E from args.");
759 }
760
765 {
766 if (des_value()) {
767 if (m_has_value) {
768 destroy_at(std::addressof(m_value));
769 } else {
770 destroy_at(std::addressof(m_error));
771 }
772 }
773 }
774
778 DExpected &operator=(const DExpected &) = delete;
779
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),
788 bool>::type = true>
789 DExpected &operator=(const DExpected &_x) noexcept(
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)
792 {
793 if (_x.m_has_value)
794 this->assign_val(_x.m_value);
795 else
796 this->assign_err(_x.m_error);
797 return *this;
798 }
799
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),
809 bool>::type = true>
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)
813 {
814 if (_x.m_has_value)
815 assign_val(std::move(_x.m_value));
816 else
817 assign_err(std::move(_x.m_error));
818 return *this;
819 }
820
826 template <
827 typename U = T,
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),
833 bool>::type = true>
835 {
836 assign_val(std::forward<U>(_v));
837 return *this;
838 }
839
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),
849 bool>::type = true>
851 {
852 assign_err(_e.error());
853 return *this;
854 }
855
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),
866 bool>::type = true>
868 {
869 assign_err(std::move(_e).error());
870 return *this;
871 }
872
879 template <typename... Args>
880 T &emplace(Args &&...args) noexcept
881 {
882 static_assert(std::is_nothrow_constructible<T, Args...>::value, "type T should have nothrow_constructible");
883 if (m_has_value)
884 destroy_at(std::addressof(m_value));
885 else {
886 destroy_at(std::addressof(m_error));
887 m_has_value = true;
888 }
889 construct_at(std::addressof(m_value), std::forward<Args>(args)...);
890 return m_value;
891 }
892
901 template <typename U, typename... Args>
902 T &emplace(std::initializer_list<U> li, Args &&...args) noexcept
903 {
904 static_assert(std::is_nothrow_constructible<T, std::initializer_list<U> &, Args...>::value,
905 "type T should have a noexcept constructor");
906 if (m_has_value)
907 destroy_at(std::addressof(m_value));
908 else {
909 destroy_at(std::addressof(m_error));
910 }
911 construct_at(std::addressof(m_value), li, std::forward<Args>(args)...);
912 return m_value;
913 }
914
915 // TODO:需要swap吗?
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),
923 bool>::type = true>
924 void
925 swap(DExpected &_x) noexcept(std::is_nothrow_move_constructible<T>::value and std::is_nothrow_move_constructible<E>::value)
926 {
927 if (m_has_value) {
928 if (_x.m_has_value) {
929 using std::swap;
930 swap(m_value, _x.m_value);
931 } else {
932 this->swap_val_err(_x);
933 }
934 } else {
935 if (_x.m_has_value)
936 _x.swap_val_err(*this);
937 else {
938 using std::swap;
939 swap(m_error, _x.m_error);
940 }
941 }
942 }
943
948 const T *operator->() const noexcept
949 {
950 assert(m_has_value);
951 return std::addressof(m_value);
952 }
953
958 T *operator->() noexcept
959 {
960 assert(m_has_value);
961 return std::addressof(m_value);
962 }
963
968 const T &operator*() const &noexcept
969 {
970 assert(m_has_value);
971 return m_value;
972 }
973
978 T &operator*() &noexcept
979 {
980 assert(m_has_value);
981 return m_value;
982 }
983
988 const T &&operator*() const &&noexcept
989 {
990 assert(m_has_value);
991 return std::move(m_value);
992 }
993
998 T &&operator*() &&noexcept
999 {
1000 assert(m_has_value);
1001 return std::move(m_value);
1002 }
1003
1008 constexpr explicit operator bool() const noexcept { return m_has_value; }
1009
1014 constexpr bool hasValue() const noexcept { return m_has_value; }
1015
1020 const T &value() const &
1021 {
1022 if (likely(m_has_value)) {
1023 return m_value;
1024 }
1025 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(m_error));
1026 }
1027
1032 T &value() &
1033 {
1034 if (likely(m_has_value)) {
1035 return m_value;
1036 }
1037 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(m_error));
1038 }
1039
1045 const T &&value() const &&
1046 {
1047 if (likely(m_has_value)) {
1048 return std::move(m_value);
1049 }
1050 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(m_error));
1051 }
1052
1058 T &&value() &&
1059 {
1060 if (likely(m_has_value)) {
1061 return std::move(m_value);
1062 }
1063 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(m_error));
1064 }
1065
1070 const E &error() const &noexcept
1071 {
1072 assert(!m_has_value);
1073 return m_error;
1074 }
1075
1080 E &error() &noexcept
1081 {
1082 assert(!m_has_value);
1083 return m_error;
1084 }
1085
1091 const E &&error() const &&noexcept
1092 {
1093 assert(!m_has_value);
1094 return std::move(m_error);
1095 }
1096
1102 E &&error() &&noexcept
1103 {
1104 assert(!m_has_value);
1105 return std::move(m_error);
1106 }
1107
1108 // TODO:因为无法确定U转T时是否会抛出异常,所以都按抛出异常来
1115 template <typename U>
1116 T value_or(U &&_v) const &
1117 {
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.");
1120 if (m_has_value)
1121 return m_value;
1122 return static_cast<T>(std::forward<U>(_v));
1123 }
1124
1132 template <typename U>
1133 T value_or(U &&_v) &&
1134 {
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.");
1137 if (m_has_value)
1138 return std::move(m_value);
1139 return static_cast<T>(std::forward<U>(_v));
1140 }
1141
1145 template <typename U, typename E2, typename std::enable_if<!std::is_void<U>::value, bool>::type = true>
1146 friend bool
1148 const DExpected<U, E2> &_y) noexcept(noexcept(bool(*_x == *_y)) and noexcept(bool(_x.error() == _y.error())))
1149 {
1150 if (_x.hasValue())
1151 return _y.hasValue() and bool(*_x == *_y);
1152 else
1153 return !_y.hasValue() and bool(_x.error() == _x.error());
1154 }
1155
1159 template <typename U>
1160 friend constexpr bool operator==(const DExpected &_x, const U &_v) noexcept(noexcept(bool(*_x == _v)))
1161 {
1162 return _x.hasValue() && bool(*_x == _v);
1163 }
1164
1168 template <typename E2>
1169 friend constexpr bool operator==(const DExpected &_x,
1170 const DUnexpected<E2> &_e) noexcept(noexcept(bool(_x.error() == _e.error())))
1171 {
1172 return !_x.hasValue() && bool(_x.error() == _e.error());
1173 }
1174
1178 friend void swap(DExpected &_x, DExpected &_y) noexcept(noexcept(_x.swap(_y))) { _x.swap(_y); }
1179
1180private:
1181 bool m_has_value;
1182 union
1183 {
1184 T m_value;
1185 E m_error;
1186 };
1187};
1188
1193template <typename E>
1194class DExpected<void, E>
1195{
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; }
1198
1199 template <typename, typename>
1200 friend class DExpected;
1201
1202 template <typename U, typename G, typename Unex = DUnexpected<E>>
1203 static constexpr bool __cons_from_DExpected()
1204 {
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;
1208 }
1209
1210 template <typename V>
1211 void assign_err(V &&_v)
1212 {
1213 if (m_has_value) {
1214 construct_at(std::addressof(m_error), std::forward<V>(_v));
1215 m_has_value = false;
1216 } else {
1217 m_error = std::forward<V>(_v);
1218 }
1219 }
1220
1221public:
1222 using value_type = void;
1223 using error_type = E;
1225 template <typename U>
1227
1228 constexpr DExpected() noexcept
1229 : m_has_value(true)
1230 , m_void()
1231 {
1232 }
1233
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)
1237 , m_void()
1238 {
1239 if (!m_has_value)
1240 construct_at(std::addressof(m_error), _x.m_error);
1241 }
1242
1243 template <typename std::enable_if<std::is_move_constructible<E>::value, bool>::type = true>
1244 DExpected(DExpected &&_x) noexcept(std::is_nothrow_move_constructible<E>::value)
1245 : m_has_value(_x.m_has_value)
1246 , m_void()
1247 {
1248 if (!m_has_value)
1249 construct_at(std::addressof(m_error), std::move(_x).m_error);
1250 }
1251
1252 template <typename U,
1253 typename G,
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,
1256 bool>::type = true>
1257 explicit DExpected(const DExpected<U, G> &_x) noexcept(std::is_nothrow_constructible<E, const G &>::value)
1258 : m_has_value(_x.m_has_value)
1259 , m_void()
1260 {
1261 if (!m_has_value)
1262 construct_at(std::addressof(m_error), _x.m_error);
1263 }
1264
1265 template <typename U,
1266 typename G,
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,
1269 bool>::type = true>
1270 DExpected(const DExpected<U, G> &_x) noexcept(std::is_nothrow_constructible<E, const G &>::value)
1271 : m_has_value(_x.m_has_value)
1272 , m_void()
1273 {
1274 if (!m_has_value)
1275 construct_at(std::addressof(m_error), _x.m_error);
1276 }
1277
1278 template <typename U,
1279 typename G,
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,
1282 bool>::type = true>
1283 explicit DExpected(DExpected<U, G> &&_x) noexcept(std::is_nothrow_constructible<E, G>::value)
1284 : m_has_value(_x.m_has_value)
1285 , m_void()
1286 {
1287 if (!m_has_value)
1288 construct_at(std::addressof(m_error), std::move(_x).m_error);
1289 }
1290
1291 template <typename U,
1292 typename G,
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,
1295 bool>::type = true>
1296 DExpected(DExpected<U, G> &&_x) noexcept(std::is_nothrow_constructible<E, G>::value)
1297 : m_has_value(_x.m_has_value)
1298 , m_void()
1299 {
1300 if (!m_has_value)
1301 construct_at(std::addressof(m_error), std::move(_x).m_error);
1302 }
1303
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,
1306 bool>::type = true>
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())
1310 {
1311 }
1312
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,
1315 bool>::type = true>
1316 constexpr DExpected(const DUnexpected<G> &_u) noexcept(std::is_nothrow_constructible<E, const G &>::value)
1317 : m_has_value(false)
1318 , m_error(_u.error())
1319 {
1320 }
1321
1322 template <
1323 typename G = E,
1324 typename std::enable_if<std::is_constructible<E, G>::value and !std::is_convertible<G, E>::value, bool>::type = true>
1325 constexpr explicit DExpected(DUnexpected<G> &&_u) noexcept(std::is_nothrow_constructible<E, G>::value)
1326 : m_has_value(false)
1327 , m_error(std::move(_u).error())
1328 {
1329 }
1330
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>
1333 constexpr DExpected(DUnexpected<G> &&_u) noexcept(std::is_nothrow_constructible<E, G>::value)
1334 : m_has_value(false)
1335 , m_error(std::move(_u).error())
1336 {
1337 }
1338
1339 template <typename... Args>
1340 constexpr explicit DExpected(emplace_tag) noexcept
1341 : DExpected()
1342 {
1343 }
1344
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)...)
1349 {
1350 static_assert(std::is_constructible<E, Args...>::value, "type E can't construct from args");
1351 }
1352
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)...)
1359 {
1360 static_assert(std::is_constructible<E, std::initializer_list<U> &, Args...>::value, "type E can't construct from args");
1361 }
1362
1363 ~DExpected()
1364 {
1365 if (des_value() and !m_has_value) {
1366 destroy_at(std::addressof(m_error));
1367 }
1368 }
1369
1370 DExpected &operator=(const DExpected &) = delete;
1371
1372 template <
1373 typename std::enable_if<std::is_copy_constructible<E>::value and std::is_copy_assignable<E>::value, bool>::type = true>
1374 DExpected &operator=(const DExpected &_x) noexcept(
1375 std::is_nothrow_copy_constructible<E>::value and std::is_nothrow_copy_assignable<E>::value)
1376 {
1377 if (_x.m_has_value)
1378 emplace();
1379 else
1380 assign_err(_x.m_error);
1381 return *this;
1382 }
1383
1384 template <
1385 typename std::enable_if<std::is_move_constructible<E>::value and std::is_move_assignable<E>::value, bool>::type = true>
1386 DExpected &
1387 operator=(DExpected &&_x) noexcept(std::is_nothrow_move_constructible<E>::value and std::is_nothrow_move_assignable<E>::value)
1388 {
1389 if (_x.m_has_value)
1390 emplace();
1391 else
1392 assign_err(std::move(_x.m_error));
1393 return *this;
1394 }
1395
1396 template <typename G,
1397 typename std::enable_if<std::is_constructible<E, const G &>::value and std::is_assignable<E &, const G &>::value,
1398 bool>::type = true>
1399 DExpected &operator=(const DUnexpected<G> &_e)
1400 {
1401 assign_err(_e.error());
1402 return *this;
1403 }
1404
1405 template <
1406 typename G,
1407 typename std::enable_if<std::is_constructible<E, G>::value and std::is_assignable<E &, G>::value, bool>::type = true>
1408 DExpected &operator=(DUnexpected<G> &&_e)
1409 {
1410 assign_err(std::move(_e.error()));
1411 return *this;
1412 }
1413
1414 void emplace() noexcept
1415 {
1416 if (!m_has_value) {
1417 destroy_at(std::addressof(m_error));
1418 m_has_value = true;
1419 }
1420 }
1421
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)
1424 {
1425 if (m_has_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;
1431 }
1432 } else {
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));
1436 m_has_value = true;
1437 _x.m_has_value = false;
1438 } else {
1439 using std::swap;
1440 swap(m_error, _x.m_error);
1441 }
1442 }
1443 }
1444
1445 constexpr explicit operator bool() const noexcept { return m_has_value; }
1446
1447 constexpr bool hasValue() const noexcept { return m_has_value; }
1448
1449 void operator*() const noexcept { assert(m_has_value); }
1450
1451 void value() const &
1452 {
1453 if (likely(m_has_value))
1454 return;
1455 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(m_error));
1456 }
1457
1458 void value() &&
1459 {
1460 if (likely(m_has_value))
1461 return;
1462 _DEXPECTED_THROW_OR_ABORT(bad_result_access<E>(std::move(m_error)));
1463 }
1464
1465 const E &error() const &noexcept
1466 {
1467 assert(!m_has_value);
1468 return m_error;
1469 }
1470
1471 E &error() &noexcept
1472 {
1473 assert(!m_has_value);
1474 return m_error;
1475 }
1476
1477 const E &&error() const &&noexcept
1478 {
1479 assert(!m_has_value);
1480 return std::move(m_error);
1481 }
1482
1483 E &&error() &&noexcept
1484 {
1485 assert(!m_has_value);
1486 return std::move(m_error);
1487 }
1488
1489 template <typename U, typename E2, typename std::enable_if<std::is_void<U>::value, bool>::type = true>
1490 friend bool operator==(const DExpected &_x, const DExpected<U, E2> &_y) noexcept(noexcept(bool(_x.error() == _y.error())))
1491 {
1492 if (_x.hasValue())
1493 return _y.hasValue();
1494 else
1495 return !_y.hasValue() and bool(_x.error() == _y.error());
1496 }
1497
1498 template <typename E2>
1499 friend bool operator==(const DExpected &_x, const DUnexpected<E2> &_e) noexcept(noexcept(bool(_x.error() == _e.error())))
1500 {
1501 return !_x.hasValue() && bool(_x.error() == _e.error());
1502 }
1503
1504 // TODO:可能没有swap
1505 friend void swap(DExpected &_x, DExpected &_y) noexcept(noexcept(_x.swap(_y))) { _x.swap(_y); }
1506
1507private:
1508 bool m_has_value;
1509 union
1510 {
1511 struct
1512 {
1513 } m_void;
1514 E m_error;
1515 };
1516};
1517
1518DCORE_END_NAMESPACE
1519
1520#endif
模板类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