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 : 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 (_NEFORCE addressof(other) == this) {
236 return *this;
237 }
238 if (other) {
239 if (have_value_) {
240 *get_ptr() = *other;
241 } else {
242 _NEFORCE construct(get_ptr(), *other);
243 have_value_ = true;
244 }
245 } else {
246 reset();
247 }
248 return *this;
249 }
250
255 optional(const optional& other) {
256 if (other.have_value_) {
257 _NEFORCE construct(get_ptr(), *other);
258 have_value_ = true;
259 }
260 }
261
267 optional& operator=(const optional& other) {
268 if (_NEFORCE addressof(other) == this) {
269 return *this;
270 }
271 if (other.have_value_) {
272 if (have_value_) {
273 *get_ptr() = *other;
274 } else {
275 _NEFORCE construct(get_ptr(), *other);
276 have_value_ = true;
277 }
278 } else {
279 reset();
280 }
281 return *this;
282 }
283
289 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && is_convertible_v<U, T> &&
290 convertible_from_optional<U>::value,
291 int> = 0>
293 if (other) {
294 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
295 have_value_ = true;
296 }
297 }
298
304 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> && !is_convertible_v<U, T> &&
305 convertible_from_optional<U>::value,
306 int> = 0>
308 if (other) {
309 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
310 have_value_ = true;
311 }
312 }
313
320 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional> && is_constructible_v<T, U> &&
321 is_assignable_v<T&, U> && !convertible_from_optional<U>::value &&
322 !assignable_from_optional<U>::value,
323 int> = 0>
324 NEFORCE_CONSTEXPR20 optional& operator=(optional<U>&& other) noexcept(is_nothrow_constructible_v<T, U> &&
326 if (_NEFORCE addressof(other) == this) {
327 return *this;
328 }
329 if (other) {
330 if (have_value_) {
331 *get_ptr() = _NEFORCE move(*other);
332 } else {
333 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
334 have_value_ = true;
335 }
336 } else {
337 reset();
338 }
339 return *this;
340 }
341
346 optional(optional&& other) noexcept {
347 if (other.have_value_) {
348 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
349 have_value_ = true;
350 other.reset();
351 }
352 }
353
359 optional& operator=(optional&& other) noexcept {
360 if (addressof(other) == this) {
361 return *this;
362 }
363
364 if (other.have_value_) {
365 if (have_value_) {
366 *get_ptr() = _NEFORCE move(*other);
367 } else {
368 _NEFORCE construct(get_ptr(), _NEFORCE move(*other));
369 have_value_ = true;
370 }
371 other.reset();
372 } else {
373 reset();
374 }
375
376 return *this;
377 }
378
384 template <typename U, enable_if_t<is_constructible_v<T, U&>, int> = 0>
385 constexpr optional(const optional<U&>& other) {
386 if (other) {
387 _NEFORCE construct(get_ptr(), *other);
388 have_value_ = true;
389 }
390 }
391
398 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
399 NEFORCE_CONSTEXPR20 optional& operator=(const optional<U&>& other) {
400 if (other) {
401 if (have_value_) {
402 *get_ptr() = *other;
403 } else {
404 _NEFORCE construct(get_ptr(), *other);
405 have_value_ = true;
406 }
407 } else {
408 reset();
409 }
410 return *this;
411 }
412
418 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
419 constexpr explicit optional(inplace_construct_tag,
420 Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) :
421 have_value_(true) {
422 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
423 }
424
432 template <typename U, typename... Types,
434 constexpr explicit optional(inplace_construct_tag, std::initializer_list<U> ilist, Types&&... args) noexcept(
436 have_value_(true) {
437 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
438 }
439
443 NEFORCE_CONSTEXPR20 ~optional() noexcept { reset(); }
444
450 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
451 NEFORCE_CONSTEXPR20 void emplace(Types&&... args) noexcept(is_nothrow_constructible_v<T, Types...>) {
452 reset();
453 _NEFORCE construct(get_ptr(), _NEFORCE forward<Types>(args)...);
454 have_value_ = true;
455 }
456
464 template <typename U, typename... Types,
466 NEFORCE_CONSTEXPR20 void
467 emplace(std::initializer_list<U> ilist,
468 Types&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) {
469 reset();
470 _NEFORCE construct(get_ptr(), ilist, _NEFORCE forward<Types>(args)...);
471 have_value_ = true;
472 }
473
477 NEFORCE_CONSTEXPR20 void reset() noexcept {
478 if (have_value_) {
479 _NEFORCE destroy(get_ptr());
480 have_value_ = false;
481 }
482 }
483
488 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return have_value_; }
489
494 constexpr explicit operator bool() const noexcept { return have_value_; }
495
501 constexpr const_reference value() const& {
502 if (!have_value_) {
503 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
504 }
505 return *get_ptr();
506 }
507
513 constexpr reference value() & {
514 if (!have_value_) {
515 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
516 }
517 return *get_ptr();
518 }
519
525 constexpr const value_type&& value() const&& {
526 if (!have_value_) {
527 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
528 }
529 return _NEFORCE move(*get_ptr());
530 }
531
537 constexpr value_type&& value() && {
538 if (!have_value_) {
539 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no value"));
540 }
541 return _NEFORCE move(*get_ptr());
542 }
543
549 constexpr value_type value_or(value_type value) const& noexcept(is_nothrow_copy_constructible_v<value_type>) {
550 if (!have_value_) {
551 return value;
552 }
553 return *get_ptr();
554 }
555
561 constexpr value_type value_or(value_type value) && noexcept(is_nothrow_move_constructible_v<value_type>) {
562 if (!have_value_) {
563 return value;
564 }
565 return _NEFORCE move(*get_ptr());
566 }
567
574 template <typename F, enable_if_t<is_invocable_v<F> && is_copy_constructible_v<T>, int> = 0>
575 constexpr optional or_else(F&& f) const& {
576 if (have_value_) {
577 return *this;
578 }
579 return _NEFORCE forward<F>(f)();
580 }
581
588 template <typename F, enable_if_t<is_invocable_v<F> && is_move_constructible_v<T>, int> = 0>
589 constexpr optional or_else(F&& f) && {
590 if (have_value_) {
591 return _NEFORCE move(*this);
592 }
593 return _NEFORCE forward<F>(f)();
594 }
595
602 template <typename F>
603 constexpr decltype(auto) and_then(F&& f) const& {
604 if (have_value_) {
605 return _NEFORCE forward<F>(f)(*get_ptr());
606 }
607 return remove_cvref_t<decltype(f(*get_ptr()))>{};
608 }
609
616 template <typename F>
617 constexpr decltype(auto) and_then(F&& f) & {
618 if (have_value_) {
619 return _NEFORCE forward<F>(f)(*get_ptr());
620 }
621 return remove_cvref_t<decltype(f(*get_ptr()))>{};
622 }
623
630 template <typename F>
631 constexpr decltype(auto) and_then(F&& f) const&& {
632 if (have_value_) {
633 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
634 }
635 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
636 }
637
644 template <typename F>
645 constexpr decltype(auto) and_then(F&& f) && {
646 if (have_value_) {
647 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
648 }
649 return remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>{};
650 }
651
658 template <typename F>
659 constexpr auto transform(F&& f) const& -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
660 if (have_value_) {
661 return _NEFORCE forward<F>(f)(*get_ptr());
662 }
663 return none;
664 }
665
672 template <typename F>
673 constexpr auto transform(F&& f) & -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
674 if (have_value_) {
675 return _NEFORCE forward<F>(f)(*get_ptr());
676 }
677 return none;
678 }
679
686 template <typename F>
687 constexpr auto transform(F&& f) const&& -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
688 if (have_value_) {
689 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
690 }
691 return none;
692 }
693
700 template <typename F>
701 constexpr auto transform(F&& f) && -> optional<remove_cvref_t<decltype(f(_NEFORCE move(*get_ptr())))>> {
702 if (have_value_) {
703 return _NEFORCE forward<F>(f)(_NEFORCE move(*get_ptr()));
704 }
705 return none;
706 }
707
712 constexpr const_pointer operator->() const noexcept { return get_ptr(); }
713
718 constexpr pointer operator->() noexcept { return get_ptr(); }
719
724 constexpr const_reference operator*() const& noexcept { return *get_ptr(); }
725
730 constexpr reference operator*() & noexcept { return *get_ptr(); }
731
736 constexpr const value_type&& operator*() const&& noexcept { return _NEFORCE move(*get_ptr()); }
737
742 constexpr value_type&& operator*() && noexcept { return _NEFORCE move(*get_ptr()); }
743
749 constexpr bool operator==(const optional& rhs) const noexcept {
750 if (have_value_ != rhs.have_value_) {
751 return false;
752 }
753 if (have_value_) {
754 return *get_ptr() == *rhs.get_ptr();
755 }
756 return true;
757 }
758
764 constexpr bool operator<(const optional& rhs) const noexcept {
765 if (!have_value_ || !rhs.have_value_) {
766 return false;
767 }
768 return *get_ptr() < *rhs.get_ptr();
769 }
770
771 constexpr bool operator==(none_t) const noexcept { return !have_value_; }
772 constexpr bool operator!=(none_t) const noexcept { return have_value_; }
773 constexpr bool operator>(none_t) const noexcept { return have_value_; }
774 constexpr bool operator<(none_t) const noexcept { return false; }
775 constexpr bool operator>=(none_t) const noexcept { return true; }
776 constexpr bool operator<=(none_t) const noexcept { return !have_value_; }
777
778 friend constexpr bool operator==(none_t, const optional& rhs) noexcept { return !rhs.have_value_; }
779 friend constexpr bool operator!=(none_t, const optional& rhs) noexcept { return rhs.have_value_; }
780 friend constexpr bool operator>(none_t, const optional&) noexcept { return false; }
781 friend constexpr bool operator<(none_t, const optional& rhs) noexcept { return rhs.have_value_; }
782 friend constexpr bool operator>=(none_t, const optional& rhs) noexcept { return !rhs.have_value_; }
783 friend constexpr bool operator<=(none_t, const optional&) noexcept { return true; }
784
789 constexpr size_t to_hash() const noexcept {
790 return have_value_ ? hash<T>()(*get_ptr()) : constants::FNV_OFFSET_BASIS;
791 }
792
797 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept(is_nothrow_move_constructible_v<T> &&
799 if (_NEFORCE addressof(other) == this) {
800 return;
801 }
802 if (have_value_ && other.have_value_) {
803 _NEFORCE swap(*this, other);
804 } else if (have_value_) {
805 other.emplace(_NEFORCE move(**this));
806 reset();
807 } else if (other.have_value_) {
808 optional::emplace(_NEFORCE move(*other));
809 other.reset();
810 }
811 }
812};
813
814
824template <typename T>
826 static_assert(is_object_v<T> && !is_array_v<T>, "optional<T&> requires T to be an object type.");
827
828public:
829 using value_type = T&;
830 using reference = T&;
831 using const_reference = const T&;
832 using pointer = T*;
833 using const_pointer = const T*;
834
835private:
836 T* ptr_ = nullptr;
837
838 template <typename U>
839 using convertible_from_optional_ref = disjunction<is_convertible<U&, T&>, is_convertible<const U&, T&>>;
840
841public:
846 constexpr optional(none_t n = none) noexcept {}
847
852 constexpr optional(T& value) noexcept :
853 ptr_(_NEFORCE addressof(value)) {}
854
860 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
861 constexpr optional(U& value) noexcept :
862 ptr_(_NEFORCE addressof(value)) {}
863
869 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
870 constexpr explicit optional(U& value) noexcept :
871 ptr_(_NEFORCE addressof(value)) {}
872
878 template <typename U, enable_if_t<convertible_from_optional_ref<U>::value, int> = 0>
879 constexpr optional(const _NEFORCE optional<U&>& other) noexcept :
880 ptr_(other.ptr_) {}
881
887 template <typename U, enable_if_t<!convertible_from_optional_ref<U>::value && is_constructible_v<T&, U&>, int> = 0>
888 constexpr explicit optional(const _NEFORCE optional<U&>& other) noexcept :
889 ptr_(other.ptr_) {}
890
898 NEFORCE_CONSTEXPR20 optional& operator=(none_t n) noexcept {
899 ptr_ = nullptr;
900 return *this;
901 }
902
909 template <typename U = T, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
910 NEFORCE_CONSTEXPR20 optional& operator=(U& value) {
911 if (ptr_) {
912 *ptr_ = value;
913 } else {
914 ptr_ = _NEFORCE addressof(value);
915 }
916 return *this;
917 }
918
925 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
926 NEFORCE_CONSTEXPR20 optional& operator=(const _NEFORCE optional<U&>& other) {
927 if (this != _NEFORCE addressof(other)) {
928 if (other.ptr_) {
929 if (ptr_) {
930 *ptr_ = *other.ptr_;
931 } else {
932 ptr_ = other.ptr_;
933 }
934 } else {
935 ptr_ = nullptr;
936 }
937 }
938 return *this;
939 }
940
945 constexpr optional(const optional& other) noexcept = default;
946
952 NEFORCE_CONSTEXPR20 optional& operator=(const optional& other) noexcept = default;
953
958 constexpr optional(optional&& other) noexcept :
959 ptr_(other.ptr_) {}
960
966 NEFORCE_CONSTEXPR20 optional& operator=(optional&& other) noexcept {
967 ptr_ = other.ptr_;
968 return *this;
969 }
970
971 template <typename... Types>
972 constexpr optional(inplace_construct_tag, Types&&...) = delete;
973
977 ~optional() noexcept { ptr_ = nullptr; }
978
985 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
986 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
987 ptr_ = _NEFORCE addressof(value);
988 return *ptr_;
989 }
990
997 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
998 NEFORCE_CONSTEXPR20 T& emplace(U& value) noexcept {
999 ptr_ = _NEFORCE addressof(value);
1000 return *ptr_;
1001 }
1002
1006 NEFORCE_CONSTEXPR20 void reset() noexcept { ptr_ = nullptr; }
1007
1011 NEFORCE_NODISCARD constexpr bool has_value() const noexcept { return ptr_ != nullptr; }
1012
1017 constexpr explicit operator bool() const noexcept { return ptr_ != nullptr; }
1018
1024 constexpr const T& value() const& {
1025 if (!ptr_) {
1026 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1027 }
1028 return *ptr_;
1029 }
1030
1036 constexpr T& value() & {
1037 if (!ptr_) {
1038 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1039 }
1040 return *ptr_;
1041 }
1042
1048 constexpr const T&& value() const&& {
1049 if (!ptr_) {
1050 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1051 }
1052 return *ptr_;
1053 }
1054
1060 constexpr T&& value() && {
1061 if (!ptr_) {
1062 NEFORCE_THROW_EXCEPTION(optional_exception("optional have no reference"));
1063 }
1064 return *ptr_;
1065 }
1066
1072 template <typename U>
1073 constexpr T value_or(U&& value) const& {
1074 if (ptr_) {
1075 return *ptr_;
1076 }
1077 return _NEFORCE forward<U>(value);
1078 }
1079
1085 template <typename U>
1086 constexpr T value_or(U&& value) && {
1087 if (ptr_) {
1088 return _NEFORCE move(*ptr_);
1089 }
1090 return _NEFORCE forward<U>(value);
1091 }
1092
1099 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1100 constexpr optional or_else(F&& f) const& {
1101 if (ptr_) {
1102 return *this;
1103 }
1104 return _NEFORCE forward<F>(f)();
1105 }
1106
1113 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1114 constexpr optional or_else(F&& f) && {
1115 if (ptr_) {
1116 return _NEFORCE move(*this);
1117 }
1118 return _NEFORCE forward<F>(f)();
1119 }
1120
1127 template <typename F>
1128 constexpr decltype(auto) and_then(F&& f) const& {
1129 if (ptr_) {
1130 return _NEFORCE forward<F>(f)(*ptr_);
1131 }
1132 return remove_cvref_t<decltype(f(*ptr_))>{};
1133 }
1134
1141 template <typename F>
1142 constexpr decltype(auto) and_then(F&& f) & {
1143 if (ptr_) {
1144 return _NEFORCE forward<F>(f)(*ptr_);
1145 }
1146 return remove_cvref_t<decltype(f(*ptr_))>{};
1147 }
1148
1155 template <typename F>
1156 constexpr decltype(auto) and_then(F&& f) const&& {
1157 if (ptr_) {
1158 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1159 }
1160 return remove_cvref_t<decltype(f(*ptr_))>{};
1161 }
1162
1169 template <typename F>
1170 constexpr decltype(auto) and_then(F&& f) && {
1171 if (ptr_) {
1172 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1173 }
1174 return remove_cvref_t<decltype(f(*ptr_))>{};
1175 }
1176
1183 template <typename F>
1184 constexpr auto transform(F&& f) const& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1185 if (ptr_) {
1186 return _NEFORCE forward<F>(f)(*ptr_);
1187 }
1188 return none;
1189 }
1190
1197 template <typename F>
1198 constexpr auto transform(F&& f) & -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1199 if (ptr_) {
1200 return _NEFORCE forward<F>(f)(*ptr_);
1201 }
1202 return none;
1203 }
1204
1211 template <typename F>
1212 constexpr auto transform(F&& f) const&& -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1213 if (ptr_) {
1214 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1215 }
1216 return none;
1217 }
1218
1225 template <typename F>
1226 constexpr auto transform(F&& f) && -> _NEFORCE optional<remove_cvref_t<decltype(f(*ptr_))>> {
1227 if (ptr_) {
1228 return _NEFORCE forward<F>(f)(_NEFORCE move(*ptr_));
1229 }
1230 return none;
1231 }
1232
1237 constexpr const T* operator->() const noexcept { return ptr_; }
1238
1243 constexpr T* operator->() noexcept { return ptr_; }
1244
1249 constexpr const T& operator*() const& noexcept { return *ptr_; }
1250
1255 constexpr T& operator*() & noexcept { return *ptr_; }
1256
1261 constexpr const T&& operator*() const&& noexcept { return *ptr_; }
1262
1267 constexpr T&& operator*() && noexcept { return *ptr_; }
1268
1274 constexpr bool operator==(const optional& rhs) const noexcept {
1275 if (ptr_ == nullptr || rhs.ptr_ == nullptr) {
1276 return ptr_ == rhs.ptr_;
1277 }
1278 return *ptr_ == *rhs.ptr_;
1279 }
1280
1286 constexpr bool operator<(const optional& rhs) const noexcept { return ptr_ && rhs.ptr_ && *ptr_ < *rhs.ptr_; }
1287
1288 constexpr bool operator==(none_t) const noexcept { return ptr_ == nullptr; }
1289 constexpr bool operator!=(none_t) const noexcept { return ptr_ != nullptr; }
1290 constexpr bool operator>(none_t) const noexcept { return ptr_ != nullptr; }
1291 constexpr bool operator<(none_t) const noexcept { return false; }
1292 constexpr bool operator>=(none_t) const noexcept { return true; }
1293 constexpr bool operator<=(none_t) const noexcept { return ptr_ == nullptr; }
1294
1295 friend constexpr bool operator==(none_t, const optional& rhs) noexcept { return rhs.ptr_ == nullptr; }
1296 friend constexpr bool operator!=(none_t, const optional& rhs) noexcept { return rhs.ptr_ != nullptr; }
1297 friend constexpr bool operator>(none_t, const optional&) noexcept { return false; }
1298 friend constexpr bool operator<(none_t, const optional& rhs) noexcept { return rhs.ptr_ != nullptr; }
1299 friend constexpr bool operator>=(none_t, const optional& rhs) noexcept { return rhs.ptr_ == nullptr; }
1300 friend constexpr bool operator<=(none_t, const optional&) noexcept { return true; }
1301
1306 constexpr size_t to_hash() const noexcept {
1307 return ptr_ ? hash<remove_cvref_t<T>>()(*ptr_) : constants::FNV_OFFSET_BASIS;
1308 }
1309
1314 NEFORCE_CONSTEXPR20 void swap(optional& other) noexcept { _NEFORCE swap(ptr_, other.ptr_); }
1315};
1316
1317#ifdef NEFORCE_STANDARD_17
1318template <typename T>
1319optional(T) -> optional<T>;
1320#endif
1321
1322
1329template <typename T, enable_if_t<is_constructible_v<decay_t<T>, T>, int> = 0>
1333
1341template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
1342constexpr optional<T> make_optional(Args&&... args) noexcept(is_nothrow_constructible_v<T, Args...>) {
1343 return optional<T>{inplace_construct_tag{}, _NEFORCE forward<Args>(args)...};
1344}
1345
1355template <typename T, typename U, typename... Args>
1357make_optional(std::initializer_list<U> ilist,
1358 Args&&... args) noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>) {
1359 return optional<T>{inplace_construct_tag{}, ilist, _NEFORCE forward<Args>(args)...};
1360}
1361
1368template <typename T>
1369constexpr optional<T&> make_optional(T& value) noexcept {
1370 return optional<T&>{value};
1371}
1372
1376template <typename T>
1378
1379
1387template <typename T>
1388constexpr const T& get(const optional<T>& opt) {
1389 return static_cast<const T&>(static_cast<const optional<T>&>(opt).value());
1390}
1391
1399template <typename T>
1400constexpr T& get(optional<T>& opt) {
1401 return static_cast<T&>(static_cast<optional<T>&>(opt).value());
1402}
1403
1411template <typename T>
1412constexpr const T&& get(const optional<T>&& opt) {
1413 return static_cast<const T&&>(static_cast<const optional<T>&&>(opt).value());
1414}
1415
1423template <typename T>
1424constexpr T&& get(optional<T>&& opt) {
1425 return static_cast<T&&>(static_cast<optional<T>&&>(opt).value());
1426}
1427 // Optional
1429
1430NEFORCE_END_NAMESPACE__
1431#endif // NEFORCE_CORE_UTILITY_OPTIONAL_HPP__
NEFORCE_CONSTEXPR20 void reset() noexcept
重置引用
constexpr const T & operator*() const &noexcept
常量左值解引用运算符
constexpr T && operator*() &&noexcept
右值解引用运算符
NEFORCE_CONSTEXPR20 optional & operator=(const optional &other) noexcept=default
复制赋值运算符
const T & const_reference
常量引用类型
NEFORCE_CONSTEXPR20 optional & operator=(optional &&other) noexcept
移动赋值运算符
constexpr auto transform(F &&f) &-> _NEFORCE optional< remove_cvref_t< decltype(f(*ptr_))> >
左值转换操作
constexpr bool operator<(const optional &rhs) const noexcept
小于比较运算符
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 &
取出存储的引用的拷贝值
NEFORCE_NODISCARD constexpr bool has_value() const noexcept
检查是否持有引用
NEFORCE_CONSTEXPR20 optional & operator=(U &value)
从引用赋值
constexpr const T * operator->() const noexcept
常量箭头运算符
constexpr T & value() &
获取左值引用
constexpr optional(optional &&other) noexcept
移动构造函数
NEFORCE_CONSTEXPR20 T & emplace(U &value) noexcept
隐式转换原位构造引用
constexpr optional(T &value) noexcept
从引用构造
NEFORCE_CONSTEXPR20 optional & operator=(const _NEFORCE optional< U & > &other)
从引用可选值赋值
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) &&
右值然后操作
constexpr bool operator==(const optional &rhs) const noexcept
等于比较运算符
T * pointer
指针类型
const T * const_pointer
常量指针类型
~optional() 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 &
常量左值否则操作
NEFORCE_CONSTEXPR20 optional & operator=(none_t n) noexcept
空值赋值运算符
NEFORCE_CONSTEXPR20 void swap(optional &other) noexcept
交换两个可选值
可选值类
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr auto transform(F &&f) const &&-> optional< remove_cvref_t< decltype(f(_NEFORCE move(*get_ptr())))> >
右值转换操作
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 const_reference operator*() const &noexcept
常量左值解引用运算符
NEFORCE_CONSTEXPR20 optional & operator=(const optional< U & > &other)
从引用可选值赋值
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 >)
从值隐式转换构造
NEFORCE_CONSTEXPR20 void reset() noexcept
重置可选值为空
constexpr const value_type && operator*() const &&noexcept
常量右值解引用运算符
optional(const optional &other)
复制构造函数
constexpr optional(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U >)
从可选值隐式转换移动构造
NEFORCE_CONSTEXPR20 void emplace(Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造值
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
计算哈希值
optional & operator=(optional &&other) noexcept
移动赋值运算符
NEFORCE_NODISCARD constexpr bool has_value() const 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 value_type value_or(value_type value) &&noexcept(is_nothrow_move_constructible_v< value_type >)
取出存储的值的移出值
NEFORCE_CONSTEXPR20 optional & operator=(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从可选值移动赋值
optional & operator=(const optional &other)
复制赋值运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
NEFORCE_CONSTEXPR20 optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr value_type && value() &&
取出存储的值
constexpr const_pointer operator->() const noexcept
常量箭头运算符
constexpr optional or_else(F &&f) &&
右值否则操作
NEFORCE_CONSTEXPR20 optional & operator=(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & > &&is_nothrow_assignable_v< T &, const U & >)
从可选值复制赋值
constexpr optional(inplace_construct_tag, Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造
NEFORCE_CONSTEXPR20 ~optional() noexcept
析构函数
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
NEFORCE_CONSTEXPR20 void emplace(std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造值
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 operator==(const optional &rhs) const noexcept
等于比较运算符
NEFORCE_CONSTEXPR20 void swap(optional &other) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_swappable_v< T >)
交换两个可选值
constexpr pointer operator->() noexcept
箭头运算符
NEFORCE_CONSTEXPR20 optional & operator=(U &&value) noexcept(is_nothrow_constructible_v< T, U > &&is_nothrow_assignable_v< T &, U >)
从值赋值
constexpr const value_type && value() const &&
取出存储的值
constexpr reference value() &
取出存储的值
constexpr bool operator<(const optional &rhs) const noexcept
小于比较运算符
optional(optional &&other) noexcept
移动构造函数
内存构造和销毁函数
异常处理框架
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
NEFORCE_INLINE17 constexpr bool is_reference_v
is_reference的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_object_v
is_object的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_array_v
is_array的便捷变量模板
NEFORCE_INLINE17 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
等于空指针比较
NEFORCE_CONSTEXPR20 T * construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
NEFORCE_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
NEFORCE_INLINE17 constexpr none_t none
默认空表示
NEFORCE_NODISCARD constexpr bool operator<=(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于等于比较运算符
NEFORCE_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
NEFORCE_NODISCARD constexpr bool operator>(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
大于比较运算符
NEFORCE_NODISCARD constexpr bool operator>=(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
大于等于比较运算符
constexpr optional< decay_t< T > > make_optional(T &&value) noexcept(is_nothrow_constructible_v< optional< decay_t< T > >, T >)
从值创建可选值
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重载
NEFORCE_INLINE17 constexpr bool is_nothrow_swappable_v
is_nothrow_swappable的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_nothrow_assignable_v
is_nothrow_assignable的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_nothrow_constructible_v
is_nothrow_constructible的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_assignable_v
is_assignable的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_constructible_v
is_constructible的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_nothrow_move_constructible_v
is_nothrow_move_constructible的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_nothrow_copy_constructible_v
is_nothrow_copy_constructible的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_same_v
is_same的便捷变量模板
NEFORCE_INLINE17 constexpr bool is_any_of_v
is_any_of的便捷变量模板
bool_constant< true > true_type
表示true的类型
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)
构造函数
NEFORCE_NODISCARD int code() const noexcept
获取异常码
NEFORCE_NODISCARD const char * type() const noexcept
获取异常类型
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
原位构造标签
判断类型是否可以使用指定类型的值进行赋值
判断类型是否可以使用指定参数构造
判断类型From是否可以隐式转换为类型To
空状态类型
optional访问异常