NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
optional.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
2#define NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
3
10
11#include <initializer_list>
16NEFORCE_BEGIN_NAMESPACE__
17
23
28struct optional_exception final : memory_exception {
29 explicit optional_exception(const char* info = "Access the Null Value of Optional.", const char* type = static_type,
30 const int code = 0) noexcept :
31 memory_exception(info, type, code) {}
32
33 explicit optional_exception(const exception& e) :
34 memory_exception(e) {}
35
36 ~optional_exception() override = default;
37 static constexpr auto static_type = "optional_exception";
38};
39 // Exceptions
41
47
48template <typename T>
49class optional;
50
51
52template <typename T>
53struct is_optional : false_type {};
54
55template <typename T>
56struct is_optional<optional<T>> : true_type {};
57
58template <typename T>
59NEFORCE_INLINE17 bool is_optional_v = is_optional<T>::value;
60
61
69template <typename T>
70class optional : public icommon<optional<T>> {
72 "optional do not contains none_t and inplace_construct_tag types.");
73 static_assert(is_object_v<T> && !is_array_v<T>, "optional only contains non-array object types.");
74 static_assert(!is_reference_v<T>, "optional of reference type should use optional<T&> specialization.");
75
76public:
77 using value_type = T;
78 using pointer = T*;
79 using reference = T&;
80 using const_pointer = const T*;
81 using const_reference = const T&;
82
83private:
84 template <typename U>
87
88 template <typename U>
89 using convertible_from_optional =
94
95 template <typename U>
96 using assignable_from_optional =
99
100 bool have_value_ = false;
101 aligned_storage_t<sizeof(T), alignof(T)> storage_;
102
103 constexpr T* get_ptr() noexcept { return reinterpret_cast<T*>(&storage_); }
104 constexpr const T* get_ptr() const noexcept { return reinterpret_cast<const T*>(&storage_); }
105
106public:
113 constexpr optional(none_t n = none) noexcept {}
114
120 NEFORCE_CONSTEXPR20 optional& operator=(none_t n) noexcept {
121 reset();
122 return *this;
123 }
124
130 template <typename U, enable_if_t<is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
132 int> = 0>
134 have_value_(true) {
135 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
136 }
137
143 template <typename U, enable_if_t<is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
145 int> = 0>
146 explicit constexpr optional(U&& value) noexcept(is_nothrow_constructible_v<T, U>) :
147 have_value_(true) {
148 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
149 }
150
155 explicit constexpr optional(const T& value) noexcept(is_nothrow_copy_constructible_v<T>) :
156 have_value_(true) {
157 _NEFORCE construct(get_ptr(), value);
158 }
159
164 explicit constexpr optional(T&& value) noexcept(is_nothrow_move_constructible_v<T>) :
165 have_value_(true) {
166 _NEFORCE construct(get_ptr(), _NEFORCE move(value));
167 }
168
175 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> &&
176 negation_v<conjunction<is_scalar<T>, is_same<T, decay_t<U>>>> &&
177 is_constructible_v<T, U> && is_assignable_v<T&, U>,
178 int> = 0>
179 NEFORCE_CONSTEXPR20 optional& operator=(U&& value) noexcept(is_nothrow_constructible_v<T, U> &&
181 if (have_value_) {
182 auto temp = T(_NEFORCE forward<U>(value));
183 *get_ptr() = _NEFORCE move(temp);
184 } else {
185 _NEFORCE construct(get_ptr(), _NEFORCE forward<U>(value));
186 have_value_ = true;
187 }
188 return *this;
189 }
190
196 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
197 is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
198 int> = 0>
200 if (other) {
201 _NEFORCE construct(get_ptr(), *other);
202 have_value_ = true;
203 }
204 }
205
211 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
212 !is_convertible_v<const U&, T> && !convertible_from_optional<U>::value,
213 int> = 0>
214 constexpr explicit optional(const optional<U>& other) noexcept(is_nothrow_constructible_v<T, const U&>) {
215 if (other) {
216 _NEFORCE construct(get_ptr(), *other);
217 have_value_ = true;
218 }
219 }
220
227 template <typename U = T,
231 int> = 0>
232 NEFORCE_CONSTEXPR20 optional&
235 if (other) {
236 if (have_value_) {
237 *get_ptr() = *other;
238 } else {
239 _NEFORCE construct(get_ptr(), *other);
240 have_value_ = true;
241 }
242 } else {
243 reset();
244 }
245 return *this;
246 }
247
252 optional(const optional& other) {
253 if (other.have_value_) {
254 _NEFORCE construct(get_ptr(), *other);
255 have_value_ = true;
256 }
257 }
258
264 optional& operator=(const optional& other) {
265 if (_NEFORCE addressof(other) == this) {
266 return *this;
267 }
268 if (other.have_value_) {
269 if (have_value_) {
270 *get_ptr() = *other;
271 } else {
272 _NEFORCE construct(get_ptr(), *other);
273 have_value_ = true;
274 }
275 } else {
276 reset();
277 }
278 return *this;
279 }
280
286 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && is_convertible_v<U, T> &&
287 !convertible_from_optional<U>::value,
288 int> = 0>
290 if (other) {
291 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
292 have_value_ = true;
293 }
294 }
295
301 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && !is_convertible_v<U, T> &&
302 !convertible_from_optional<U>::value,
303 int> = 0>
305 if (other) {
306 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
307 have_value_ = true;
308 }
309 }
310
317 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> && is_constructible_v<T, U> &&
318 is_assignable_v<T&, U> && !convertible_from_optional<U>::value &&
319 !assignable_from_optional<U>::value,
320 int> = 0>
321 NEFORCE_CONSTEXPR20 optional& operator=(optional<U>&& other) noexcept(is_nothrow_constructible_v<T, U> &&
323 if (other) {
324 if (have_value_) {
325 *get_ptr() = _NEFORCE move(*other);
326 } else {
327 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
328 have_value_ = true;
329 }
330 } else {
331 reset();
332 }
333 return *this;
334 }
335
340 optional(optional&& other) noexcept {
341 if (other.have_value_) {
342 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
343 have_value_ = true;
344 other.reset();
345 }
346 }
347
353 optional& operator=(optional&& other) noexcept {
354 if (addressof(other) == this) {
355 return *this;
356 }
357
358 if (other.have_value_) {
359 if (have_value_) {
360 *get_ptr() = _NEFORCE move(*other);
361 } else {
362 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
363 have_value_ = true;
364 }
365 other.reset();
366 } else {
367 reset();
368 }
369
370 return *this;
371 }
372
378 template <typename U, enable_if_t<is_constructible_v<T, U&>, int> = 0>
379 constexpr optional(const optional<U&>& other) {
380 if (other) {
381 _NEFORCE construct(get_ptr(), *other);
382 have_value_ = true;
383 }
384 }
385
392 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
393 NEFORCE_CONSTEXPR20 optional& operator=(const optional<U&>& other) {
394 if (other) {
395 if (have_value_) {
396 *get_ptr() = *other;
397 } else {
398 _NEFORCE construct(get_ptr(), *other);
399 have_value_ = true;
400 }
401 } else {
402 reset();
403 }
404 return *this;
405 }
406
412 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
413 constexpr explicit optional(inplace_construct_tag /*unused*/,
414 Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) :
415 have_value_(true) {
416 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
417 }
418
426 template <typename U, typename... Types,
428 constexpr explicit optional(
429 inplace_construct_tag /*unused*/, std::initializer_list<U> ilist,
430 Types&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) :
431 have_value_(true) {
432 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
433 }
434
438 NEFORCE_CONSTEXPR20 ~optional() noexcept { reset(); }
439
445 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
446 NEFORCE_CONSTEXPR20 void emplace(Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) {
447 reset();
448 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
449 have_value_ = true;
450 }
451
459 template <typename U, typename... Types,
461 NEFORCE_CONSTEXPR20 void
462 emplace(std::initializer_list<U> ilist,
463 Types&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) {
464 reset();
465 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
466 have_value_ = true;
467 }
468
472 NEFORCE_CONSTEXPR20 void reset() noexcept {
473 if (have_value_) {
474 _NEFORCE destroy(get_ptr());
475 have_value_ = false;
476 }
477 }
478
483 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return have_value_; }
484
489 constexpr explicit operator bool() const noexcept { return have_value_; }
490
496 constexpr const_reference value() const& {
497 if (!have_value_) {
498 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
499 }
500 return *get_ptr();
501 }
502
508 constexpr reference value() & {
509 if (!have_value_) {
510 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
511 }
512 return *get_ptr();
513 }
514
520 constexpr const value_type&& value() const&& {
521 if (!have_value_) {
522 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
523 }
524 return _NEFORCE move(*get_ptr());
525 }
526
532 constexpr value_type&& value() && {
533 if (!have_value_) {
534 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
535 }
536 return _NEFORCE move(*get_ptr());
537 }
538
544 constexpr value_type value_or(value_type value) const& noexcept(is_nothrow_copy_constructible_v<value_type>) {
545 if (!have_value_) {
546 return value;
547 }
548 return *get_ptr();
549 }
550
556 constexpr value_type value_or(value_type value) && noexcept(is_nothrow_move_constructible_v<value_type>) {
557 if (!have_value_) {
558 return value;
559 }
560 return _NEFORCE move(*get_ptr());
561 }
562
569 template <typename F, enable_if_t<is_invocable_v<F> && is_copy_constructible_v<T>, int> = 0>
570 constexpr optional or_else(F&& f) const& {
571 if (have_value_) {
572 return *this;
573 }
574 return _NEFORCE forward<F>(f)();
575 }
576
583 template <typename F, enable_if_t<is_invocable_v<F> && is_move_constructible_v<T>, int> = 0>
584 constexpr optional or_else(F&& f) && {
585 if (have_value_) {
586 return _NEFORCE move(*this);
587 }
588 return _NEFORCE forward<F>(f)();
589 }
590
597 template <typename F>
598 constexpr decltype(auto) and_then(F&& f) const& {
599 if (have_value_) {
600 return _NEFORCE forward<F>(f)(*get_ptr());
601 }
602 return remove_cvref_t<decltype(f(*get_ptr()))>{};
603 }
604
611 template <typename F>
612 constexpr decltype(auto) and_then(F&& f) & {
613 if (have_value_) {
614 return _NEFORCE forward<F>(f)(*get_ptr());
615 }
616 return remove_cvref_t<decltype(f(*get_ptr()))>{};
617 }
618
625 template <typename F>
626 constexpr decltype(auto) and_then(F&& f) const&& {
627 if (have_value_) {
628 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
629 }
630 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
631 }
632
639 template <typename F>
640 constexpr decltype(auto) and_then(F&& f) && {
641 if (have_value_) {
642 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
643 }
644 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
645 }
646
653 template <typename F>
654 constexpr auto transform(F&& f) const& -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
655 if (have_value_) {
656 return _NEFORCE forward<F>(f)(*get_ptr());
657 }
658 return none;
659 }
660
667 template <typename F>
668 constexpr auto transform(F&& f) & -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
669 if (have_value_) {
670 return _NEFORCE forward<F>(f)(*get_ptr());
671 }
672 return none;
673 }
674
681 template <typename F>
682 constexpr auto transform(F&& f) const&& -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
683 if (have_value_) {
684 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
685 }
686 return none;
687 }
688
695 template <typename F>
696 constexpr auto transform(F&& f) && -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
697 if (have_value_) {
698 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
699 }
700 return none;
701 }
702
707 constexpr const_pointer operator->() const noexcept { return get_ptr(); }
708
713 constexpr pointer operator->() noexcept { return get_ptr(); }
714
719 constexpr const_reference operator*() const& noexcept { return *get_ptr(); }
720
725 constexpr reference operator*() & noexcept { return *get_ptr(); }
726
731 constexpr const value_type&& operator*() const&& noexcept { return _NEFORCE move(*get_ptr()); }
732
737 constexpr value_type&& operator*() && noexcept { return _NEFORCE move(*get_ptr()); }
738
744 NEFORCE_NODISCARD constexpr bool equal_to(const optional& rhs) const noexcept {
745 if (have_value_ != rhs.have_value_) {
746 return false;
747 }
748 if (have_value_) {
749 return *get_ptr() == *rhs.get_ptr();
750 }
751 return true;
752 }
753
759 NEFORCE_NODISCARD constexpr bool less_than(const optional& rhs) const noexcept {
760 if (!have_value_ || !rhs.have_value_) {
761 return false;
762 }
763 return *get_ptr() < *rhs.get_ptr();
764 }
765
766 constexpr bool operator==(none_t /*unused*/) const noexcept { return !have_value_; }
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 false; }
770 constexpr bool operator>=(none_t /*unused*/) const noexcept { return true; }
771 constexpr bool operator<=(none_t /*unused*/) const noexcept { return !have_value_; }
772
773 friend constexpr bool operator==(none_t /*unused*/, const optional& rhs) noexcept { return !rhs.have_value_; }
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& /*unused*/) noexcept { return false; }
776 friend constexpr bool operator<(none_t /*unused*/, const optional& rhs) noexcept { return rhs.have_value_; }
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& /*unused*/) noexcept { return true; }
779
784 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
785 return have_value_ ? hash<T>()(*get_ptr()) : constants::FNV_OFFSET_BASIS;
786 }
787
792 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept(is_nothrow_move_constructible_v<T> &&
794 if (_NEFORCE addressof(other) == this) {
795 return;
796 }
797 if (have_value_ && other.have_value_) {
798 _NEFORCE swap(*this, other);
799 } else if (have_value_) {
800 other.emplace(_NEFORCE move(**this));
801 reset();
802 } else if (other.have_value_) {
803 optional::emplace(_NEFORCE move(*other));
804 other.reset();
805 }
806 }
807};
808
809
819template <typename T>
820class optional<T&> : public icommon<optional<T&>> {
821 static_assert(is_object_v<T> && !is_array_v<T>, "optional<T&> requires T to be an object type.");
822
823public:
824 using value_type = T&;
825 using reference = T&;
826 using const_reference = const T&;
827 using pointer = T*;
828 using const_pointer = const T*;
829
830private:
831 T* ptr_ = nullptr;
832
833 template <typename U>
834 using convertible_from_optional_ref = disjunction<is_convertible<U&, T&>, is_convertible<const U&, T&>>;
835
836public:
841 constexpr optional(none_t n = none) noexcept {}
842
847 constexpr optional(T& value) noexcept :
848 ptr_(_NEFORCE addressof(value)) {}
849
855 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
856 constexpr optional(U& value) noexcept :
857 ptr_(_NEFORCE addressof(value)) {}
858
864 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
865 constexpr explicit optional(U& value) noexcept :
866 ptr_(_NEFORCE addressof(value)) {}
867
873 template <typename U, enable_if_t<convertible_from_optional_ref<U>::value, int> = 0>
874 constexpr optional(const _NEFORCE optional<U&>& other) noexcept :
875 ptr_(other.ptr_) {}
876
882 template <typename U, enable_if_t<!convertible_from_optional_ref<U>::value && is_constructible_v<T&, U&>, int> = 0>
883 constexpr explicit optional(const _NEFORCE optional<U&>& other) noexcept :
884 ptr_(other.ptr_) {}
885
893 NEFORCE_CONSTEXPR20 optional& operator=(none_t n) noexcept {
894 ptr_ = nullptr;
895 return *this;
896 }
897
904 template <typename U = T, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
905 NEFORCE_CONSTEXPR20 optional& operator=(U& value) {
906 ptr_ = _NEFORCE addressof(value);
907 return *this;
908 }
909
916 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
917 NEFORCE_CONSTEXPR20 optional& operator=(const optional<U&>& other) {
918 if (this != _NEFORCE addressof(other)) {
919 ptr_ = other.ptr_;
920 }
921 return *this;
922 }
923
928 constexpr optional(const optional& other) noexcept = default;
929
935 NEFORCE_CONSTEXPR20 optional& operator=(const optional& other) noexcept = default;
936
941 constexpr optional(optional&& other) noexcept :
942 ptr_(other.ptr_) {}
943
949 NEFORCE_CONSTEXPR20 optional& operator=(optional&& other) noexcept {
950 ptr_ = other.ptr_;
951 return *this;
952 }
953
954 template <typename... Types>
955 constexpr optional(inplace_construct_tag, Types&&...) = delete;
956
960 ~optional() noexcept { ptr_ = nullptr; }
961
968 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
969 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
970 ptr_ = _NEFORCE addressof(value);
971 return *ptr_;
972 }
973
980 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
981 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
982 ptr_ = _NEFORCE addressof(value);
983 return *ptr_;
984 }
985
989 NEFORCE_CONSTEXPR20 void reset() noexcept { ptr_ = nullptr; }
990
994 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return ptr_ != nullptr; }
995
1000 constexpr explicit operator bool() const noexcept { return ptr_ != nullptr; }
1001
1007 constexpr const T& value() const& {
1008 if (ptr_ == nullptr) {
1009 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1010 }
1011 return *ptr_;
1012 }
1013
1019 constexpr T& value() & {
1020 if (ptr_ == nullptr) {
1021 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1022 }
1023 return *ptr_;
1024 }
1025
1031 constexpr const T&& value() const&& {
1032 if (ptr_ == nullptr) {
1033 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1034 }
1035 return *ptr_;
1036 }
1037
1043 constexpr T&& value() && {
1044 if (ptr_ == nullptr) {
1045 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1046 }
1047 return *ptr_;
1048 }
1049
1055 template <typename U>
1056 constexpr T value_or(U&& value) const& {
1057 if (ptr_) {
1058 return *ptr_;
1059 }
1060 return _NEFORCE forward<U>(value);
1061 }
1062
1068 template <typename U>
1069 constexpr T value_or(U&& value) && {
1070 if (ptr_) {
1071 return _NEFORCE move(*ptr_);
1072 }
1073 return _NEFORCE forward<U>(value);
1074 }
1075
1082 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1083 constexpr optional or_else(F&& f) const& {
1084 if (ptr_) {
1085 return *this;
1086 }
1087 return _NEFORCE forward<F>(f)();
1088 }
1089
1096 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1097 constexpr optional or_else(F&& f) && {
1098 if (ptr_) {
1099 return _NEFORCE move(*this);
1100 }
1101 return _NEFORCE forward<F>(f)();
1102 }
1103
1110 template <typename F>
1111 constexpr decltype(auto) and_then(F&& f) const& {
1112 if (ptr_) {
1113 return _NEFORCE forward<F>(f)(*ptr_);
1114 }
1115 return remove_cvref_t<decltype(f(*ptr_))>{};
1116 }
1117
1124 template <typename F>
1125 constexpr decltype(auto) and_then(F&& f) & {
1126 if (ptr_) {
1127 return _NEFORCE forward<F>(f)(*ptr_);
1128 }
1129 return remove_cvref_t<decltype(f(*ptr_))>{};
1130 }
1131
1138 template <typename F>
1139 constexpr decltype(auto) and_then(F&& f) const&& {
1140 if (ptr_) {
1141 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1142 }
1143 return remove_cvref_t<decltype(f(*ptr_))>{};
1144 }
1145
1152 template <typename F>
1153 constexpr decltype(auto) and_then(F&& f) && {
1154 if (ptr_) {
1155 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1156 }
1157 return remove_cvref_t<decltype(f(*ptr_))>{};
1158 }
1159
1166 template <typename F>
1167 constexpr auto transform(F&& f) const& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1168 if (ptr_) {
1169 return _NEFORCE forward<F>(f)(*ptr_);
1170 }
1171 return none;
1172 }
1173
1180 template <typename F>
1181 constexpr auto transform(F&& f) & -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1182 if (ptr_) {
1183 return _NEFORCE forward<F>(f)(*ptr_);
1184 }
1185 return none;
1186 }
1187
1194 template <typename F>
1195 constexpr auto transform(F&& f) const&& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1196 if (ptr_) {
1197 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1198 }
1199 return none;
1200 }
1201
1208 template <typename F>
1209 constexpr auto transform(F&& f) && -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1210 if (ptr_) {
1211 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1212 }
1213 return none;
1214 }
1215
1220 constexpr const T* operator->() const noexcept { return ptr_; }
1221
1226 constexpr T* operator->() noexcept { return ptr_; }
1227
1232 constexpr const T& operator*() const& noexcept { return *ptr_; }
1233
1238 constexpr T& operator*() & noexcept { return *ptr_; }
1239
1244 constexpr const T&& operator*() const&& noexcept { return *ptr_; }
1245
1250 constexpr T&& operator*() && noexcept { return *ptr_; }
1251
1257 constexpr bool equal_to(const optional& rhs) const noexcept {
1258 if (ptr_ == nullptr || rhs.ptr_ == nullptr) {
1259 return ptr_ == rhs.ptr_;
1260 }
1261 return *ptr_ == *rhs.ptr_;
1262 }
1263
1269 constexpr bool less_than(const optional& rhs) const noexcept { return ptr_ && rhs.ptr_ && *ptr_ < *rhs.ptr_; }
1270
1271 constexpr bool operator==(none_t /*unused*/) const noexcept { return ptr_ == nullptr; }
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 false; }
1275 constexpr bool operator>=(none_t /*unused*/) const noexcept { return true; }
1276 constexpr bool operator<=(none_t /*unused*/) const noexcept { return ptr_ == nullptr; }
1277
1278 friend constexpr bool operator==(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ == nullptr; }
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& /*unused*/) noexcept { return false; }
1281 friend constexpr bool operator<(none_t /*unused*/, const optional& rhs) noexcept { return rhs.ptr_ != nullptr; }
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& /*unused*/) noexcept { return true; }
1284
1289 NEFORCE_NODISCARD constexpr size_t to_hash() const noexcept {
1290 return ptr_ ? hash<remove_cvref_t<T>>()(*ptr_) : constants::FNV_OFFSET_BASIS;
1291 }
1292
1297 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept { _NEFORCE swap(ptr_, other.ptr_); }
1298};
1299
1300#ifdef NEFORCE_STANDARD_17
1301template <typename T>
1302optional(T) -> optional<T>;
1303#endif
1304
1305
1313template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
1314constexpr optional<T> make_optional(Args&&... args) noexcept(is_nothrow_constructible_v<T, Args...>) {
1315 return optional<T>{inplace_construct_tag{}, _NEFORCE forward<Args>(args)...};
1316}
1317
1327template <typename T, typename U, typename... Args>
1329make_optional(std::initializer_list<U> ilist,
1330 Args&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>) {
1331 return optional<T>{inplace_construct_tag{}, ilist, _NEFORCE forward<Args>(args)...};
1332}
1333
1334
1342template <typename T>
1343constexpr const T& get(const optional<T>& opt) {
1344 return static_cast<const T&>(static_cast<const optional<T>&>(opt).value());
1345}
1346
1354template <typename T>
1355constexpr T& get(optional<T>& opt) {
1356 return static_cast<T&>(static_cast<optional<T>&>(opt).value());
1357}
1358
1366template <typename T>
1367constexpr const T&& get(const optional<T>&& opt) {
1368 return static_cast<const T&&>(static_cast<const optional<T>&&>(opt).value());
1369}
1370
1378template <typename T>
1379constexpr T&& get(optional<T>&& opt) {
1380 return static_cast<T&&>(static_cast<optional<T>&&>(opt).value());
1381}
1382 // Optional
1384
1385NEFORCE_END_NAMESPACE__
1386#endif // NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
constexpr void swap(optional &other) noexcept
交换两个可选值
constexpr T & emplace(U &value) noexcept
隐式转换原位构造引用
constexpr optional & operator=(const optional &other) noexcept=default
复制赋值运算符
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值(重新绑定)
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
constexpr const T & operator*() const &noexcept
常量左值解引用运算符
constexpr T && operator*() &&noexcept
右值解引用运算符
const T & const_reference
常量引用类型
constexpr bool has_value() const noexcept
检查是否持有引用
constexpr auto transform(F &&f) &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
左值转换操作
constexpr T value_or(U &&value) &&
取出存储的引用的移动值
constexpr auto transform(F &&f) const &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量右值转换操作
constexpr optional(const _NEFORCE optional< U & > &other) noexcept
从引用可选值隐式转换复制构造
constexpr T * operator->() noexcept
箭头运算符
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr optional(U &value) noexcept
从可转换引用隐式转换构造
constexpr T value_or(U &&value) const &
取出存储的引用的拷贝值
constexpr const T * operator->() const noexcept
常量箭头运算符
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr T & value() &
获取左值引用
constexpr optional(optional &&other) noexcept
移动构造函数
constexpr optional(T &value) noexcept
从引用构造
constexpr const T && value() const &&
获取常量右值引用
T & value_type
值类型
constexpr optional(const optional &other) noexcept=default
复制构造函数
constexpr const T & value() const &
获取常量左值引用
T & reference
引用类型
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
T * pointer
指针类型
constexpr void reset() noexcept
重置引用
const T * const_pointer
常量指针类型
constexpr optional & operator=(optional &&other) noexcept
移动赋值运算符
~optional() noexcept
析构函数
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr auto transform(F &&f) &&-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
右值转换操作
constexpr optional(none_t n=none) noexcept
默认构造函数
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr T && value() &&
获取右值引用
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr const T && operator*() const &&noexcept
常量右值解引用运算符
constexpr auto transform(F &&f) const &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
常量左值转换操作
constexpr T & operator*() &noexcept
左值解引用运算符
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr optional & operator=(U &value)
从引用赋值(重新绑定)
可选值类
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr auto transform(F &&f) const &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
右值转换操作
constexpr optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr value_type && operator*() &&noexcept
右值解引用运算符
constexpr value_type value_or(value_type value) const &noexcept(is_nothrow_copy_constructible_v< value_type >)
取出存储的值的拷贝值
constexpr optional(inplace_construct_tag, std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造
constexpr auto transform(F &&f) &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
左值转换操作
constexpr void emplace(Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造值
constexpr void swap(optional &other) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_swappable_v< T >)
交换两个可选值
constexpr const_reference operator*() const &noexcept
常量左值解引用运算符
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr optional(const optional< U & > &other)
从引用可选值赋值
constexpr optional(const T &value) noexcept(is_nothrow_copy_constructible_v< T >)
从值拷贝构造
constexpr optional(U &&value) noexcept(is_nothrow_constructible_v< T, U >)
从值隐式转换构造
constexpr const value_type && operator*() const &&noexcept
常量右值解引用运算符
optional(const optional &other)
复制构造函数
constexpr ~optional() noexcept
析构函数
constexpr optional(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U >)
从可选值隐式转换移动构造
constexpr reference operator*() &noexcept
左值解引用运算符
constexpr auto transform(F &&f) &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
常量右值转换操作
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr void reset() noexcept
重置可选值为空
optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr optional(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & >)
从可选值隐式转换复制构造
constexpr auto transform(F &&f) const &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
常量左值转换操作
constexpr void emplace(std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造值
constexpr value_type value_or(value_type value) &&noexcept(is_nothrow_move_constructible_v< value_type >)
取出存储的值的移出值
optional & operator=(const optional &other)
复制赋值运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
constexpr value_type && value() &&
取出存储的值
constexpr optional & operator=(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & > &&is_nothrow_assignable_v< T &, const U & >)
从可选值复制赋值
constexpr const_pointer operator->() const noexcept
常量箭头运算符
constexpr optional or_else(F &&f) &&
右值否则操作
constexpr optional(inplace_construct_tag, Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr optional & operator=(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从可选值移动赋值
constexpr optional & operator=(const optional< U & > &other)
从引用可选值赋值
constexpr bool equal_to(const optional &rhs) const noexcept
等于比较运算符
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional(none_t n=none) noexcept
从空值构造
constexpr optional(T &&value) noexcept(is_nothrow_move_constructible_v< T >)
从值移动构造
constexpr const_reference value() const &
取出存储的值
constexpr bool has_value() const noexcept
检查是否包含值
constexpr pointer operator->() noexcept
箭头运算符
constexpr const value_type && value() const &&
取出存储的值
constexpr optional & operator=(U &&value) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从值赋值
constexpr reference value() &
取出存储的值
optional(optional &&other) noexcept
移动构造函数
constexpr bool less_than(const optional &rhs) const noexcept
小于比较运算符
内存构造和销毁函数
异常处理框架
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr bool is_object_v
is_object的便捷变量模板
constexpr bool is_reference_v
is_reference的便捷变量模板
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 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
constexpr T * construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
constexpr none_t none
默认空表示
constexpr optional< T > make_optional(Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
原位构造可选值
constexpr const T & get(const optional< T > &opt)
获取可选值中的值
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)))
移动范围元素
void swap()=delete
删除无参数的swap重载
constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
constexpr bool is_constructible_v
is_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_assignable_v
is_assignable的便捷变量模板
constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
constexpr bool is_nothrow_assignable_v
is_nothrow_assignable的便捷变量模板
constexpr bool is_any_of_v
is_any_of的便捷变量模板
bool_constant< true > true_type
表示true的类型
constexpr bool is_same_v
is_same的便捷变量模板
bool_constant< false > false_type
表示false的类型
integral_constant< bool, Value > bool_constant
布尔常量包装器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
统一调用接口
空状态类型
类型集合的逻辑或操作
exception(const char *info=static_type, const char *type=static_type, const int code=0)
构造函数
const char * type() const noexcept
获取异常类型
int code() const noexcept
获取异常码
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
原位构造标签
判断类型是否可以使用指定类型的值进行赋值
判断类型是否可以使用指定参数构造
判断类型From是否可以隐式转换为类型To
空状态类型
optional访问异常