NexusForce 1.0.0
A rigorously engineered full-stack C++ backend library.
载入中...
搜索中...
未找到
optional.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
2#define NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
3
10
11#include <initializer_list>
12#include <new>
17NEFORCE_BEGIN_NAMESPACE__
18
24
29struct optional_exception final : memory_exception {
30 explicit optional_exception(const char* info = "Access the Null Value of Optional.") noexcept :
31 memory_exception(info) {}
32
33 explicit optional_exception(const exception& e) :
34 memory_exception(e) {}
35
36 ~optional_exception() override = default;
37
38 NEFORCE_NODISCARD const char* type() const noexcept override { return "optional_exception"; }
39};
40 // Exceptions
42
48
49template <typename T>
50class optional;
51
52
53template <typename T>
54struct is_optional : false_type {};
55
56template <typename T>
57struct is_optional<optional<T>> : true_type {};
58
59template <typename T>
60NEFORCE_INLINE17 bool is_optional_v = is_optional<T>::value;
61
62
70template <typename T>
71class optional : public icommon<optional<T>> {
73 "optional do not contains none_t and inplace_construct_tag types.");
74 static_assert(is_object_v<T> && !is_array_v<T>, "optional only contains non-array object types.");
75 static_assert(!is_reference_v<T>, "optional of reference type should use optional<T&> specialization.");
76
77public:
78 using value_type = T;
79 using pointer = T*;
80 using reference = T&;
81 using const_pointer = const T*;
82 using const_reference = const T&;
83
84private:
85 template <typename U>
88
89 template <typename U>
90 using convertible_from_optional =
95
96 template <typename U>
97 using assignable_from_optional =
100
101 bool have_value_ = false;
102 aligned_storage_t<sizeof(T), alignof(T)> storage_;
103
104 constexpr T* get_ptr() noexcept { return reinterpret_cast<T*>(&storage_); }
105 constexpr const T* get_ptr() const noexcept { return reinterpret_cast<const T*>(&storage_); }
106
107public:
114 constexpr optional(none_t n = none) noexcept {}
115
121 NEFORCE_CONSTEXPR20 optional& operator=(none_t n) noexcept {
122 reset();
123 return *this;
124 }
125
131 template <typename U, enable_if_t<is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
133 int> = 0>
135 have_value_(true) {
136 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
137 }
138
144 template <typename U, enable_if_t<is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
146 int> = 0>
147 explicit constexpr optional(U&& value) noexcept(is_nothrow_constructible_v<T, U>) :
148 have_value_(true) {
149 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
150 }
151
156 constexpr optional(const T& value) noexcept(is_nothrow_copy_constructible_v<T>) :
157 have_value_(true) {
158 _NEFORCE construct(get_ptr(), value);
159 }
160
166 have_value_(true) {
167 _NEFORCE construct(get_ptr(), _NEFORCE move(value));
168 }
169
176 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> &&
177 negation_v<conjunction<is_scalar<T>, is_same<T, decay_t<U>>>> &&
178 is_constructible_v<T, U> && is_assignable_v<T&, U>,
179 int> = 0>
180 NEFORCE_CONSTEXPR20 optional& operator=(U&& value) noexcept(is_nothrow_constructible_v<T, U> &&
182 if (have_value_) {
183 auto temp = T(_NEFORCE forward<U>(value));
184 *get_ptr() = _NEFORCE move(temp);
185 } else {
186 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
187 have_value_ = true;
188 }
189 return *this;
190 }
191
197 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
198 is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
199 int> = 0>
201 if (other) {
202 _NEFORCE construct(get_ptr(), *other);
203 have_value_ = true;
204 }
205 }
206
212 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
213 !is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
214 int> = 0>
216 if (other) {
217 _NEFORCE construct(get_ptr(), *other);
218 have_value_ = true;
219 }
220 }
221
228 template <typename U = T,
230 is_assignable_v<T&, const U&> && !convertible_from_optional<U>::value &&
231 !assignable_from_optional<U>::value,
232 int> = 0>
233 NEFORCE_CONSTEXPR20 optional&
236 if (other) {
237 if (have_value_) {
238 *get_ptr() = *other;
239 } else {
240 _NEFORCE construct(get_ptr(), *other);
241 have_value_ = true;
242 }
243 } else {
244 reset();
245 }
246 return *this;
247 }
248
253 optional(const optional& other) {
254 if (other.have_value_) {
255 _NEFORCE construct(get_ptr(), *other);
256 have_value_ = true;
257 }
258 }
259
265 optional& operator=(const optional& other) {
266 if (_NEFORCE addressof(other) == this) {
267 return *this;
268 }
269 if (other.have_value_) {
270 if (have_value_) {
271 *get_ptr() = *other;
272 } else {
273 _NEFORCE construct(get_ptr(), *other);
274 have_value_ = true;
275 }
276 } else {
277 reset();
278 }
279 return *this;
280 }
281
287 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && is_convertible_v<U, T> &&
288 !convertible_from_optional<U>::value,
289 int> = 0>
291 if (other) {
292 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
293 have_value_ = true;
294 }
295 }
296
302 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && !is_convertible_v<U, T> &&
303 !convertible_from_optional<U>::value,
304 int> = 0>
306 if (other) {
307 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
308 have_value_ = true;
309 }
310 }
311
318 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> && is_constructible_v<T, U> &&
319 is_assignable_v<T&, U> && !convertible_from_optional<U>::value &&
320 !assignable_from_optional<U>::value,
321 int> = 0>
322 NEFORCE_CONSTEXPR20 optional& operator=(optional<U>&& other) noexcept(is_nothrow_constructible_v<T, U> &&
324 if (other) {
325 if (have_value_) {
326 *get_ptr() = _NEFORCE move(*other);
327 } else {
328 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
329 have_value_ = true;
330 }
331 } else {
332 reset();
333 }
334 return *this;
335 }
336
341 optional(optional&& other) noexcept {
342 if (other.have_value_) {
343 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
344 have_value_ = true;
345 other.reset();
346 }
347 }
348
354 optional& operator=(optional&& other) noexcept {
355 if (_NEFORCE addressof(other) == this) {
356 return *this;
357 }
358
359 if (other.have_value_) {
360 if (have_value_) {
361 *get_ptr() = _NEFORCE move(*other);
362 } else {
363 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
364 have_value_ = true;
365 }
366 other.reset();
367 } else {
368 reset();
369 }
370
371 return *this;
372 }
373
379 template <typename U, enable_if_t<is_constructible_v<T, U&>, int> = 0>
380 constexpr optional(const optional<U&>& other) {
381 if (other) {
382 _NEFORCE construct(get_ptr(), *other);
383 have_value_ = true;
384 }
385 }
386
393 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
394 NEFORCE_CONSTEXPR20 optional& operator=(const optional<U&>& other) {
395 if (other) {
396 if (have_value_) {
397 *get_ptr() = *other;
398 } else {
399 _NEFORCE construct(get_ptr(), *other);
400 have_value_ = true;
401 }
402 } else {
403 reset();
404 }
405 return *this;
406 }
407
413 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
414 constexpr explicit optional(inplace_construct_tag /*unused*/,
415 Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) :
416 have_value_(true) {
417 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
418 }
419
427 template <typename U, typename... Types,
429 constexpr explicit optional(
430 inplace_construct_tag /*unused*/, std::initializer_list<U> ilist,
431 Types&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) :
432 have_value_(true) {
433 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
434 }
435
439 NEFORCE_CONSTEXPR20 ~optional() noexcept { reset(); }
440
446 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
447 NEFORCE_CONSTEXPR20 void emplace(Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) {
448 reset();
449 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
450 have_value_ = true;
451 }
452
460 template <typename U, typename... Types,
462 NEFORCE_CONSTEXPR20 void
463 emplace(std::initializer_list<U> ilist,
464 Types&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) {
465 reset();
466 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
467 have_value_ = true;
468 }
469
473 NEFORCE_CONSTEXPR20 void reset() noexcept {
474 if (have_value_) {
475 _NEFORCE destroy(get_ptr());
476 have_value_ = false;
477 }
478 }
479
484 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return have_value_; }
485
490 constexpr explicit operator bool() const noexcept { return have_value_; }
491
497 constexpr const_reference value() const& {
498 if (!have_value_) {
499 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
500 }
501 return *get_ptr();
502 }
503
509 constexpr reference value() & {
510 if (!have_value_) {
511 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
512 }
513 return *get_ptr();
514 }
515
521 constexpr const value_type&& value() const&& {
522 if (!have_value_) {
523 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
524 }
525 return _NEFORCE move(*get_ptr());
526 }
527
533 constexpr value_type&& value() && {
534 if (!have_value_) {
535 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
536 }
537 return _NEFORCE move(*get_ptr());
538 }
539
545 constexpr value_type value_or(value_type value) const& noexcept(is_nothrow_copy_constructible_v<value_type>) {
546 if (!have_value_) {
547 return value;
548 }
549 return *get_ptr();
550 }
551
557 constexpr value_type value_or(value_type value) && noexcept(is_nothrow_move_constructible_v<value_type>) {
558 if (!have_value_) {
559 return value;
560 }
561 return _NEFORCE move(*get_ptr());
562 }
563
570 template <typename F, enable_if_t<is_invocable_v<F> && is_copy_constructible_v<T>, int> = 0>
571 constexpr optional or_else(F&& f) const& {
572 if (have_value_) {
573 return *this;
574 }
575 return _NEFORCE forward<F>(f)();
576 }
577
584 template <typename F, enable_if_t<is_invocable_v<F> && is_move_constructible_v<T>, int> = 0>
585 constexpr optional or_else(F&& f) && {
586 if (have_value_) {
587 return _NEFORCE move(*this);
588 }
589 return _NEFORCE forward<F>(f)();
590 }
591
598 template <typename F>
599 constexpr decltype(auto) and_then(F&& f) const& {
600 if (have_value_) {
601 return _NEFORCE forward<F>(f)(*get_ptr());
602 }
603 return remove_cvref_t<decltype(f(*get_ptr()))>{};
604 }
605
612 template <typename F>
613 constexpr decltype(auto) and_then(F&& f) & {
614 if (have_value_) {
615 return _NEFORCE forward<F>(f)(*get_ptr());
616 }
617 return remove_cvref_t<decltype(f(*get_ptr()))>{};
618 }
619
626 template <typename F>
627 constexpr decltype(auto) and_then(F&& f) const&& {
628 if (have_value_) {
629 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
630 }
631 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
632 }
633
640 template <typename F>
641 constexpr decltype(auto) and_then(F&& f) && {
642 if (have_value_) {
643 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
644 }
645 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
646 }
647
654 template <typename F>
655 constexpr auto transform(F&& f) const& -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
656 if (have_value_) {
657 return _NEFORCE forward<F>(f)(*get_ptr());
658 }
659 return none;
660 }
661
668 template <typename F>
669 constexpr auto transform(F&& f) & -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
670 if (have_value_) {
671 return _NEFORCE forward<F>(f)(*get_ptr());
672 }
673 return none;
674 }
675
682 template <typename F>
683 constexpr auto transform(F&& f) const&& -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
684 if (have_value_) {
685 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
686 }
687 return none;
688 }
689
696 template <typename F>
697 constexpr auto transform(F&& f) && -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
698 if (have_value_) {
699 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
700 }
701 return none;
702 }
703
708 constexpr const_pointer operator->() const noexcept { return get_ptr(); }
709
714 constexpr pointer operator->() noexcept { return get_ptr(); }
715
720 constexpr const_reference operator*() const& noexcept { return *get_ptr(); }
721
726 constexpr reference operator*() & noexcept { return *get_ptr(); }
727
732 constexpr const value_type&& operator*() const&& noexcept { return _NEFORCE move(*get_ptr()); }
733
738 constexpr value_type&& operator*() && noexcept { return _NEFORCE move(*get_ptr()); }
739
745 NEFORCE_NODISCARD constexpr bool equal_to(const optional& rhs) const noexcept {
746 if (have_value_ != rhs.have_value_) {
747 return false;
748 }
749 if (have_value_) {
750 return *get_ptr() == *rhs.get_ptr();
751 }
752 return true;
753 }
754
760 NEFORCE_NODISCARD constexpr bool less_than(const optional& rhs) const noexcept {
761 if (!have_value_ || !rhs.have_value_) {
762 return false;
763 }
764 return *get_ptr() < *rhs.get_ptr();
765 }
766
767 constexpr bool operator==(none_t /*unused*/) const noexcept { return !have_value_; }
768 constexpr bool operator!=(none_t /*unused*/) const noexcept { return have_value_; }
769 constexpr bool operator>(none_t /*unused*/) const noexcept { return have_value_; }
770 constexpr bool operator<(none_t /*unused*/) const noexcept { return false; }
771 constexpr bool operator>=(none_t /*unused*/) const noexcept { return true; }
772 constexpr bool operator<=(none_t /*unused*/) const noexcept { return !have_value_; }
773
774 friend constexpr bool operator==(none_t /*unused*/, const optional& rhs) noexcept { return !rhs.have_value_; }
775 friend constexpr bool operator!=(none_t /*unused*/, const optional& rhs) noexcept { return rhs.have_value_; }
776 friend constexpr bool operator>(none_t /*unused*/, const optional& /*unused*/) noexcept { return false; }
777 friend constexpr bool operator<(none_t /*unused*/, const optional& rhs) noexcept { return rhs.have_value_; }
778 friend constexpr bool operator>=(none_t /*unused*/, const optional& rhs) noexcept { return !rhs.have_value_; }
779 friend constexpr bool operator<=(none_t /*unused*/, const optional& /*unused*/) noexcept { return true; }
780
785 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
786 return have_value_ ? hash<T>()(*get_ptr()) : constants::FNV_OFFSET_BASIS;
787 }
788
793 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept(is_nothrow_move_constructible_v<T> &&
795 if (_NEFORCE addressof(other) == this) {
796 return;
797 }
798 if (have_value_ && other.have_value_) {
799 _NEFORCE swap(*this, other);
800 } else if (have_value_) {
801 other.emplace(_NEFORCE move(**this));
802 reset();
803 } else if (other.have_value_) {
804 optional::emplace(_NEFORCE move(*other));
805 other.reset();
806 }
807 }
808};
809
810
820template <typename T>
821class optional<T&> : public icommon<optional<T&>> {
822 static_assert(is_object_v<T> && !is_array_v<T>, "optional<T&> requires T to be an object type.");
823
824public:
825 using value_type = T&;
826 using reference = T&;
827 using const_reference = const T&;
828 using pointer = T*;
829 using const_pointer = const T*;
830
831private:
832 T* ptr_ = nullptr;
833
834 template <typename U>
835 using convertible_from_optional_ref = disjunction<is_convertible<U&, T&>, is_convertible<const U&, T&>>;
836
837public:
842 constexpr optional(none_t n = none) noexcept {}
843
848 constexpr optional(T& value) noexcept :
849 ptr_(_NEFORCE addressof(value)) {}
850
856 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
857 constexpr optional(U& value) noexcept :
858 ptr_(_NEFORCE addressof(value)) {}
859
865 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
866 constexpr explicit optional(U& value) noexcept :
867 ptr_(_NEFORCE addressof(value)) {}
868
874 template <typename U, enable_if_t<convertible_from_optional_ref<U>::value, int> = 0>
875 constexpr optional(const _NEFORCE optional<U&>& other) noexcept :
876 ptr_(other.ptr_) {}
877
883 template <typename U, enable_if_t<!convertible_from_optional_ref<U>::value && is_constructible_v<T&, U&>, int> = 0>
884 constexpr explicit optional(const _NEFORCE optional<U&>& other) noexcept :
885 ptr_(other.ptr_) {}
886
894 NEFORCE_CONSTEXPR20 optional& operator=(none_t n) noexcept {
895 ptr_ = nullptr;
896 return *this;
897 }
898
905 template <typename U = T, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
906 NEFORCE_CONSTEXPR20 optional& operator=(U& value) {
907 ptr_ = _NEFORCE addressof(value);
908 return *this;
909 }
910
917 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
918 NEFORCE_CONSTEXPR20 optional& operator=(const optional<U&>& other) {
919 if (this != _NEFORCE addressof(other)) {
920 ptr_ = other.ptr_;
921 }
922 return *this;
923 }
924
929 constexpr optional(const optional& other) noexcept = default;
930
936 NEFORCE_CONSTEXPR20 optional& operator=(const optional& other) noexcept = default;
937
942 constexpr optional(optional&& other) noexcept :
943 ptr_(other.ptr_) {}
944
950 NEFORCE_CONSTEXPR20 optional& operator=(optional&& other) noexcept {
951 ptr_ = other.ptr_;
952 return *this;
953 }
954
955 template <typename... Types>
956 constexpr optional(inplace_construct_tag, Types&&...) = delete;
957
961 ~optional() noexcept { ptr_ = nullptr; }
962
969 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
970 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
971 ptr_ = _NEFORCE addressof(value);
972 return *ptr_;
973 }
974
981 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
982 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
983 ptr_ = _NEFORCE addressof(value);
984 return *ptr_;
985 }
986
990 NEFORCE_CONSTEXPR20 void reset() noexcept { ptr_ = nullptr; }
991
995 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return ptr_ != nullptr; }
996
1001 constexpr explicit operator bool() const noexcept { return ptr_ != nullptr; }
1002
1008 constexpr const T& value() const& {
1009 if (ptr_ == nullptr) {
1010 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1011 }
1012 return *ptr_;
1013 }
1014
1020 constexpr T& value() & {
1021 if (ptr_ == nullptr) {
1022 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1023 }
1024 return *ptr_;
1025 }
1026
1032 constexpr const T&& value() const&& {
1033 if (ptr_ == nullptr) {
1034 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1035 }
1036 return *ptr_;
1037 }
1038
1044 constexpr T&& value() && {
1045 if (ptr_ == nullptr) {
1046 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1047 }
1048 return *ptr_;
1049 }
1050
1056 template <typename U>
1057 constexpr T value_or(U&& value) const& {
1058 if (ptr_) {
1059 return *ptr_;
1060 }
1061 return _NEFORCE forward<U>(value);
1062 }
1063
1069 template <typename U>
1070 constexpr T value_or(U&& value) && {
1071 if (ptr_) {
1072 return _NEFORCE move(*ptr_);
1073 }
1074 return _NEFORCE forward<U>(value);
1075 }
1076
1083 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1084 constexpr optional or_else(F&& f) const& {
1085 if (ptr_) {
1086 return *this;
1087 }
1088 return _NEFORCE forward<F>(f)();
1089 }
1090
1097 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1098 constexpr optional or_else(F&& f) && {
1099 if (ptr_) {
1100 return _NEFORCE move(*this);
1101 }
1102 return _NEFORCE forward<F>(f)();
1103 }
1104
1111 template <typename F>
1112 constexpr decltype(auto) and_then(F&& f) const& {
1113 if (ptr_) {
1114 return _NEFORCE forward<F>(f)(*ptr_);
1115 }
1116 return remove_cvref_t<decltype(f(*ptr_))>{};
1117 }
1118
1125 template <typename F>
1126 constexpr decltype(auto) and_then(F&& f) & {
1127 if (ptr_) {
1128 return _NEFORCE forward<F>(f)(*ptr_);
1129 }
1130 return remove_cvref_t<decltype(f(*ptr_))>{};
1131 }
1132
1139 template <typename F>
1140 constexpr decltype(auto) and_then(F&& f) const&& {
1141 if (ptr_) {
1142 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1143 }
1144 return remove_cvref_t<decltype(f(*ptr_))>{};
1145 }
1146
1153 template <typename F>
1154 constexpr decltype(auto) and_then(F&& f) && {
1155 if (ptr_) {
1156 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1157 }
1158 return remove_cvref_t<decltype(f(*ptr_))>{};
1159 }
1160
1167 template <typename F>
1168 constexpr auto transform(F&& f) const& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1169 if (ptr_) {
1170 return _NEFORCE forward<F>(f)(*ptr_);
1171 }
1172 return none;
1173 }
1174
1181 template <typename F>
1182 constexpr auto transform(F&& f) & -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1183 if (ptr_) {
1184 return _NEFORCE forward<F>(f)(*ptr_);
1185 }
1186 return none;
1187 }
1188
1195 template <typename F>
1196 constexpr auto transform(F&& f) const&& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1197 if (ptr_) {
1198 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1199 }
1200 return none;
1201 }
1202
1209 template <typename F>
1210 constexpr auto transform(F&& f) && -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1211 if (ptr_) {
1212 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1213 }
1214 return none;
1215 }
1216
1221 constexpr const T* operator->() const noexcept { return ptr_; }
1222
1227 constexpr T* operator->() noexcept { return ptr_; }
1228
1233 constexpr const T& operator*() const& noexcept { return *ptr_; }
1234
1239 constexpr T& operator*() & noexcept { return *ptr_; }
1240
1245 constexpr const T&& operator*() const&& noexcept { return *ptr_; }
1246
1251 constexpr T&& operator*() && noexcept { return *ptr_; }
1252
1258 constexpr bool equal_to(const optional& rhs) const noexcept {
1259 if (ptr_ == nullptr || rhs.ptr_ == nullptr) {
1260 return ptr_ == rhs.ptr_;
1261 }
1262 return *ptr_ == *rhs.ptr_;
1263 }
1264
1270 constexpr bool less_than(const optional& rhs) const noexcept { return ptr_ && rhs.ptr_ && *ptr_ < *rhs.ptr_; }
1271
1272 constexpr bool operator==(none_t /*unused*/) const noexcept { return ptr_ == nullptr; }
1273 constexpr bool operator!=(none_t /*unused*/) const noexcept { return ptr_ != nullptr; }
1274 constexpr bool operator>(none_t /*unused*/) const noexcept { return ptr_ != nullptr; }
1275 constexpr bool operator<(none_t /*unused*/) const noexcept { return false; }
1276 constexpr bool operator>=(none_t /*unused*/) const noexcept { return true; }
1277 constexpr bool operator<=(none_t /*unused*/) const noexcept { return ptr_ == nullptr; }
1278
1279 friend constexpr bool operator==(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ == nullptr; }
1280 friend constexpr bool operator!=(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ != nullptr; }
1281 friend constexpr bool operator>(none_t /*unused*/, const optional& /*unused*/) noexcept { return false; }
1282 friend constexpr bool operator<(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ != nullptr; }
1283 friend constexpr bool operator>=(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ == nullptr; }
1284 friend constexpr bool operator<=(none_t /*unused*/, const optional& /*unused*/) noexcept { return true; }
1285
1290 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
1291 return ptr_ ? hash<remove_cvref_t<T>>()(*ptr_) : constants::FNV_OFFSET_BASIS;
1292 }
1293
1298 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept { _NEFORCE swap(ptr_, other.ptr_); }
1299};
1300
1301#ifdef NEFORCE_STANDARD_17
1302template <typename T>
1303optional(T) -> optional<T>;
1304#endif
1305
1306
1314template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
1315constexpr optional<T> make_optional(Args&&... args) noexcept(is_nothrow_constructible_v<T, Args...>) {
1316 return optional<T>{inplace_construct_tag{}, _NEFORCE forward<Args>(args)...};
1317}
1318
1328template <typename T, typename U, typename... Args>
1329constexpr enable_if_t<is_constructible_v<T, std::initializer_list<U>&, Args...>, optional<T>>
1330make_optional(std::initializer_list<U> ilist,
1331 Args&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>) {
1332 return optional<T>{inplace_construct_tag{}, ilist, _NEFORCE forward<Args>(args)...};
1333}
1334
1335
1343template <typename T>
1344constexpr const T& get(const optional<T>& opt) {
1345 return static_cast<const T&>(static_cast<const optional<T>&>(opt).value());
1346}
1347
1355template <typename T>
1356constexpr T& get(optional<T>& opt) {
1357 return static_cast<T&>(static_cast<optional<T>&>(opt).value());
1358}
1359
1367template <typename T>
1368constexpr const T&& get(const optional<T>&& opt) {
1369 return static_cast<const T&&>(static_cast<const optional<T>&&>(opt).value());
1370}
1371
1379template <typename T>
1380constexpr T&& get(optional<T>&& opt) {
1381 return static_cast<T&&>(static_cast<optional<T>&&>(opt).value());
1382}
1383 // Optional
1385
1386NEFORCE_END_NAMESPACE__
1387#endif // NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
const T * const_pointer
常量指针类型
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr void swap(optional &other) noexcept
交换两个可选值
constexpr optional(const _NEFORCE optional< U & > &other) noexcept
从引用可选值隐式转换复制构造
constexpr T * operator->() noexcept
箭头运算符
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr optional(T &value) noexcept
从引用构造
constexpr T & value() &
获取左值引用
constexpr optional(U &value) noexcept
从可转换引用隐式转换构造
constexpr optional(none_t n=none) noexcept
默认构造函数
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值(重新绑定)
constexpr auto transform(F &&f) &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
右值转换操作
constexpr optional & operator=(const optional &other) noexcept=default
复制赋值运算符
constexpr optional(optional &&other) noexcept
移动构造函数
constexpr auto transform(F &&f) const &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量左值转换操作
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr T & operator*() &noexcept
左值解引用运算符
constexpr const T * operator->() const noexcept
常量箭头运算符
constexpr T && value() &&
获取右值引用
constexpr T & emplace(U &value) noexcept
隐式转换原位构造引用
constexpr auto transform(F &&f) const &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量右值转换操作
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr T && operator*() &&noexcept
右值解引用运算符
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
constexpr auto transform(F &&f) &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
左值转换操作
constexpr const T & operator*() const &noexcept
常量左值解引用运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr T value_or(U &&value) &&
取出存储的引用的移动值
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
const T & const_reference
常量引用类型
constexpr const T & value() const &
获取常量左值引用
constexpr T value_or(U &&value) const &
取出存储的引用的拷贝值
constexpr const T && value() const &&
获取常量右值引用
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr const T && operator*() const &&noexcept
常量右值解引用运算符
constexpr void reset() noexcept
重置引用
constexpr optional(const optional &other) noexcept=default
复制构造函数
~optional() noexcept
析构函数
constexpr optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr bool has_value() const noexcept
检查是否持有引用
constexpr optional & operator=(U &value)
从引用赋值(重新绑定)
optional & operator=(const optional &other)
复制赋值运算符
constexpr auto transform(F &&f) const &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
右值转换操作
constexpr ~optional() noexcept
析构函数
constexpr const_reference value() const &
取出存储的值
optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr const_pointer operator->() const noexcept
常量箭头运算符
constexpr optional(inplace_construct_tag, Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造
constexpr optional(U &&value) noexcept(is_nothrow_constructible_v< T, U >)
从值隐式转换构造
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr optional(inplace_construct_tag, std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造
constexpr value_type && operator*() &&noexcept
右值解引用运算符
constexpr optional(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & >)
从可选值隐式转换复制构造
constexpr optional(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U >)
从可选值隐式转换移动构造
constexpr value_type && value() &&
取出存储的值
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
optional(const optional &other)
复制构造函数
constexpr reference operator*() &noexcept
左值解引用运算符
constexpr auto transform(F &&f) &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
左值转换操作
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr reference value() &
取出存储的值
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值
constexpr optional(none_t n=none) noexcept
从空值构造
constexpr void emplace(Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造值
constexpr auto transform(F &&f) const &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
常量左值转换操作
constexpr value_type value_or(value_type value) &&noexcept(is_nothrow_move_constructible_v< value_type >)
取出存储的值的移出值
constexpr bool has_value() const noexcept
检查是否包含值
constexpr optional(const optional< U & > &other)
从引用可选值赋值
constexpr const value_type && operator*() const &&noexcept
常量右值解引用运算符
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr optional(T &&value) noexcept(is_nothrow_move_constructible_v< T >)
从值移动构造
constexpr void reset() noexcept
重置可选值为空
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional(const T &value) noexcept(is_nothrow_copy_constructible_v< T >)
从值拷贝构造
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr pointer operator->() noexcept
箭头运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr value_type value_or(value_type value) const &noexcept(is_nothrow_copy_constructible_v< value_type >)
取出存储的值的拷贝值
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
optional(optional &&other) noexcept
移动构造函数
constexpr optional & operator=(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & > &&is_nothrow_assignable_v< T &, const U & >)
从可选值复制赋值
constexpr optional & operator=(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从可选值移动赋值
constexpr optional & operator=(U &&value) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从值赋值
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr void swap(optional &other) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_swappable_v< T >)
交换两个可选值
constexpr void emplace(std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造值
constexpr const value_type && value() const &&
取出存储的值
constexpr auto transform(F &&f) &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
常量右值转换操作
constexpr const_reference operator*() const &noexcept
常量左值解引用运算符
内存构造和销毁函数
异常处理框架
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
enable_if_t< is_void_v< T >, future_result_t< T > > get(future< T > &f)
通用future结果获取函数
constexpr bool is_reference_v
is_reference的便捷变量模板
constexpr bool is_object_v
is_object的便捷变量模板
constexpr bool is_array_v
is_array的便捷变量模板
constexpr bool is_convertible_v
is_convertible的便捷变量模板
bool operator!=(const function< Res(Args...)> &f, nullptr_t np) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t np) noexcept
等于空指针比较
constexpr size_t FNV_OFFSET_BASIS
FNV哈希算法的偏移基础值
constexpr T * construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
constexpr void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
constexpr none_t none
默认空表示
constexpr optional< T > make_optional(Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
原位构造可选值
typename remove_cvref< T >::type remove_cvref_t
remove_cvref的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
constexpr bool is_assignable_v
is_assignable的便捷变量模板
constexpr bool is_constructible_v
is_constructible的便捷变量模板
constexpr bool is_nothrow_assignable_v
is_nothrow_assignable的便捷变量模板
constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
constexpr bool is_any_of_v
is_any_of的便捷变量模板
integral_constant< bool, Value > bool_constant
布尔常量包装器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
constexpr bool is_same_v
is_same的便捷变量模板
bool_constant< true > true_type
表示true的类型
统一调用接口
空状态类型
类型集合的逻辑或操作
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
判断类型是否可以使用指定类型的值进行赋值
判断类型是否可以使用指定参数构造
判断类型From是否可以隐式转换为类型To
空状态类型
const char * type() const noexcept override
获取异常类型