MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
optional.hpp
浏览该文件的文档.
1#ifndef MSTL_CORE_UTILITY_OPTIONAL_HPP__
2#define MSTL_CORE_UTILITY_OPTIONAL_HPP__
3
10
15#include <initializer_list>
17
23
29MSTL_ERROR_BUILD_FINAL_CLASS(optional_exception, memory_exception, "Access the Null Value of Optional.")
30
31 // Exceptions
32
33
38
39template <typename T>
40class optional;
41
49template <typename T>
51 static_assert(!is_any_of_v<remove_cv_t<T>, none_t, inplace_construct_tag>,
52 "optional do not contains none_t and inplace_construct_tag types.");
53 static_assert(is_object_v<T> && !is_array_v<T>, "optional only contains non-array object types.");
54 static_assert(!is_reference_v<T>, "optional of reference type should use optional<T&> specialization.");
55
56public:
58
59private:
60 template <typename U>
61 using is_valid_optional = bool_constant<
62 !is_any_of_v<remove_cv_t<U>, none_t, inplace_construct_tag> &&
63 is_object_v<U> &&
64 !is_array_v<U>>;
65
66 template <typename U>
67 using convertible_from_optional = disjunction<
76
77 template <typename U>
78 using assignable_from_optional = disjunction<
83
84 bool have_value_ = false;
85 aligned_storage_t<sizeof(T), alignof(T)> storage_;
86
87 constexpr T* get_ptr() noexcept {
88 return reinterpret_cast<T*>(&storage_);
89 }
90 constexpr const T* get_ptr() const noexcept {
91 return reinterpret_cast<const T*>(&storage_);
92 }
93
94 template <typename... Args>
95 void construct_value(Args&&... args) {
96 _MSTL construct(get_ptr(), _MSTL forward<Args>(args)...);
97 have_value_ = true;
98 }
99
100 void destroy_value() noexcept {
101 if (have_value_) {
102 _MSTL destroy(get_ptr());
103 have_value_ = false;
104 }
105 }
106
107public:
114 constexpr optional(none_t n = none) noexcept {}
115
121 MSTL_CONSTEXPR20 optional& operator =(none_t n) noexcept {
122 reset();
123 return *this;
124 }
125
131 template <typename U, enable_if_t<
132 is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
133 is_constructible_v<T, U> && is_convertible_v<U, T>, int
134 > = 0>
135 constexpr optional(U&& value) noexcept(is_nothrow_constructible_v<T, U>)
136 : have_value_(true) {
137 _MSTL construct(get_ptr(), _MSTL forward<U>(value));
138 }
139
145 template <typename U, enable_if_t<
146 is_valid_optional<U>::value && !is_same_v<remove_cvref_t<U>, optional> &&
147 is_constructible_v<T, U> && !is_convertible_v<U, T>, int
148 > = 0>
149 constexpr optional(U&& value) noexcept(is_nothrow_constructible_v<T, U>)
150 : have_value_(true) {
151 _MSTL construct(get_ptr(), _MSTL forward<U>(value));
152 }
153
160 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional>
161 && negation_v<conjunction<is_scalar<T>, is_same<T, decay_t<U>>>>
162 && is_constructible_v<T, U> && is_assignable_v<T&, U>, int> = 0>
163 MSTL_CONSTEXPR20 optional& operator =(U&& value)
164 noexcept(is_nothrow_constructible_v<T, U> && is_nothrow_assignable_v<T&, U>) {
165 if (have_value_) {
166 auto temp = T(_MSTL forward<U>(value));
167 *get_ptr() = _MSTL move(temp);
168 } else {
169 _MSTL construct(get_ptr(), _MSTL forward<U>(value));
170 have_value_ = true;
171 }
172 return *this;
173 }
174
180 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
181 is_convertible_v<const U&, T> && convertible_from_optional<U>::value, int> = 0>
182 constexpr optional(const optional<U>& other) noexcept(is_nothrow_constructible_v<T, const U&>) {
183 if (other) {
184 _MSTL construct(get_ptr(), *other);
185 have_value_ = true;
186 }
187 }
188
194 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, const U&> &&
195 !is_convertible_v<const U&, T> && convertible_from_optional<U>::value, int> = 0>
196 constexpr explicit optional(const optional<U>& other) noexcept(is_nothrow_constructible_v<T, const U&>) {
197 if (other) {
198 _MSTL construct(get_ptr(), *other);
199 have_value_ = true;
200 }
201 }
202
209 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional>
210 && is_constructible_v<T, const U&> && is_assignable_v<T&, const U&>
211 && !convertible_from_optional<U>::value && !assignable_from_optional<U>::value, int> = 0>
212 MSTL_CONSTEXPR20 optional& operator =(const optional<U>& other)
213 noexcept(is_nothrow_constructible_v<T, const U&> && is_nothrow_assignable_v<T&, const U&>) {
214 if (_MSTL addressof(other) == this) return *this;
215 if (other) {
216 if (have_value_) {
217 *get_ptr() = *other;
218 } else {
219 _MSTL construct(get_ptr(), *other);
220 have_value_ = true;
221 }
222 } else {
223 reset();
224 }
225 return *this;
226 }
227
232 optional(const optional& other) {
233 if (other.have_value_) {
234 _MSTL construct(get_ptr(), *other);
235 have_value_ = true;
236 }
237 }
238
244 optional& operator =(const optional& other) {
245 if (_MSTL addressof(other) == this) return *this;
246 if (other.have_value_) {
247 if (have_value_) {
248 *get_ptr() = *other;
249 } else {
250 _MSTL construct(get_ptr(), *other);
251 have_value_ = true;
252 }
253 } else {
254 reset();
255 }
256 return *this;
257 }
258
264 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> &&
265 is_convertible_v<U, T> && convertible_from_optional<U>::value, int> = 0>
266 constexpr optional(optional<U>&& other) noexcept(is_nothrow_constructible_v<T, U>) {
267 if (other) {
268 _MSTL construct(get_ptr(), _MSTL move(*other));
269 have_value_ = true;
270 }
271 }
272
278 template <typename U, enable_if_t<!is_same_v<T, U> && is_constructible_v<T, U> &&
279 !is_convertible_v<U, T> && convertible_from_optional<U>::value, int> = 0>
280 constexpr optional(optional<U>&& other) noexcept(is_nothrow_constructible_v<T, U>) {
281 if (other) {
282 _MSTL construct(get_ptr(), _MSTL move(*other));
283 have_value_ = true;
284 }
285 }
286
293 template <typename U = T, enable_if_t<!is_same_v<remove_cvref_t<U>, optional>
294 && is_constructible_v<T, U> && is_assignable_v<T&, U>
295 && !convertible_from_optional<U>::value && !assignable_from_optional<U>::value, int> = 0>
296 MSTL_CONSTEXPR20 optional& operator =(optional<U>&& other)
297 noexcept(is_nothrow_constructible_v<T, U> && is_nothrow_assignable_v<T&, U>) {
298 if (_MSTL addressof(other) == this) return *this;
299 if (other) {
300 if (have_value_) {
301 *get_ptr() = _MSTL move(*other);
302 } else {
303 _MSTL construct(get_ptr(), _MSTL move(*other));
304 have_value_ = true;
305 }
306 } else {
307 reset();
308 }
309 return *this;
310 }
311
316 optional(optional&& other) noexcept {
317 if (other.have_value_) {
318 _MSTL construct(get_ptr(), _MSTL move(*other));
319 have_value_ = true;
320 other.reset();
321 }
322 }
323
329 optional& operator =(optional&& other) noexcept {
330 if (this != &other) {
331 if (other.have_value_) {
332 if (have_value_) {
333 *get_ptr() = _MSTL move(*other);
334 } else {
335 _MSTL construct(get_ptr(), _MSTL move(*other));
336 have_value_ = true;
337 }
338 other.reset();
339 } else {
340 reset();
341 }
342 }
343 return *this;
344 }
345
352 template <typename U, enable_if_t<is_constructible_v<T, U&>, int> = 0>
353 constexpr optional(const optional<U&>& other) {
354 if (other) {
355 _MSTL construct(get_ptr(), *other);
356 have_value_ = true;
357 }
358 }
359
366 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
367 MSTL_CONSTEXPR20 optional& operator =(const optional<U&>& other) {
368 if (other) {
369 if (have_value_) {
370 *get_ptr() = *other;
371 } else {
372 _MSTL construct(get_ptr(), *other);
373 have_value_ = true;
374 }
375 } else {
376 reset();
377 }
378 return *this;
379 }
380
386 template <typename ...Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
387 constexpr explicit optional(inplace_construct_tag, Types&&... args)
388 noexcept(is_nothrow_constructible_v<T, Types...>)
389 : have_value_(true) {
390 _MSTL construct(get_ptr(), _MSTL forward<Types>(args)...);
391 }
392
400 template <typename U, typename ...Types, enable_if_t<is_constructible_v<T, std::initializer_list<U>&, Types...>, int> = 0>
401 constexpr explicit optional(inplace_construct_tag, std::initializer_list<U> ilist, Types &&...args)
402 noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>)
403 : have_value_(true) {
404 _MSTL construct(get_ptr(), ilist, _MSTL forward<Types>(args)...);
405 }
406
410 MSTL_CONSTEXPR20 ~optional() noexcept {
411 reset();
412 }
413
419 template <typename... Types, enable_if_t<is_constructible_v<T, Types...>, int> = 0>
420 MSTL_CONSTEXPR20 void emplace(Types&&... args)
421 noexcept(is_nothrow_constructible_v<T, Types...>) {
422 reset();
423 _MSTL construct(get_ptr(), _MSTL forward<Types>(args)...);
424 have_value_ = true;
425 }
426
434 template <typename U, typename... Types,
436 MSTL_CONSTEXPR20 void emplace(std::initializer_list<U> ilist, Types&&... args)
437 noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Types...>) {
438 reset();
439 _MSTL construct(get_ptr(), ilist, _MSTL forward<Types>(args)...);
440 have_value_ = true;
441 }
442
446 MSTL_CONSTEXPR20 void reset() noexcept {
447 destroy_value();
448 }
449
454 MSTL_NODISCARD constexpr bool has_value() const noexcept {
455 return have_value_;
456 }
457
462 constexpr explicit operator bool() const noexcept {
463 return have_value_;
464 }
465
471 constexpr const_reference value() const & {
472 if (!have_value_) {
473 throw_exception(optional_exception("optional have no value"));
474 }
475 return *get_ptr();
476 }
477
483 constexpr reference value() & {
484 if (!have_value_) {
485 throw_exception(optional_exception("optional have no value"));
486 }
487 return *get_ptr();
488 }
489
495 constexpr const value_type&& value() const && {
496 if (!have_value_) {
497 throw_exception(optional_exception("optional have no value"));
498 }
499 return _MSTL move(*get_ptr());
500 }
501
507 constexpr value_type&& value() && {
508 if (!have_value_) {
509 throw_exception(optional_exception("optional have no value"));
510 }
511 return _MSTL move(*get_ptr());
512 }
513
519 constexpr value_type value_or(value_type value) const &
520 noexcept(is_nothrow_copy_constructible_v<value_type>) {
521 if (!have_value_) {
522 return value;
523 }
524 return *get_ptr();
525 }
526
532 constexpr value_type value_or(value_type value) &&
533 noexcept(is_nothrow_move_constructible_v<value_type>) {
534 if (!have_value_) {
535 return value;
536 }
537 return _MSTL move(*get_ptr());
538 }
539
546 template <typename F, enable_if_t<
547 is_invocable_v<F> && is_copy_constructible_v<T>, int> = 0>
548 constexpr optional or_else(F&& f) const & {
549 if (have_value_) {
550 return *this;
551 }
552 return _MSTL forward<F>(f)();
553 }
554
561 template <typename F, enable_if_t<
562 is_invocable_v<F> && is_move_constructible_v<T>, int> = 0>
563 constexpr optional or_else(F&& f) && {
564 if (have_value_) {
565 return _MSTL move(*this);
566 }
567 return _MSTL forward<F>(f)();
568 }
569
576 template <typename F>
577 constexpr decltype(auto) and_then(F&& f) const & {
578 if (have_value_) {
579 return _MSTL forward<F>(f)(*get_ptr());
580 }
581 return remove_cvref_t<decltype(f(*get_ptr()))>{};
582 }
583
590 template <typename F>
591 constexpr decltype(auto) and_then(F&& f) & {
592 if (have_value_) {
593 return _MSTL forward<F>(f)(*get_ptr());
594 }
595 return remove_cvref_t<decltype(f(*get_ptr()))>{};
596 }
597
604 template <typename F>
605 constexpr decltype(auto) and_then(F&& f) const && {
606 if (have_value_) {
607 return _MSTL forward<F>(f)(_MSTL move(*get_ptr()));
608 }
609 return remove_cvref_t<decltype(f(_MSTL move(*get_ptr())))>{};
610 }
611
618 template <typename F>
619 constexpr decltype(auto) and_then(F&& f) && {
620 if (have_value_) {
621 return _MSTL forward<F>(f)(_MSTL move(*get_ptr()));
622 }
623 return remove_cvref_t<decltype(f(_MSTL move(*get_ptr())))>{};
624 }
625
632 template <typename F>
633 constexpr auto transform(F&& f) const & -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
634 if (have_value_) {
635 return _MSTL forward<F>(f)(*get_ptr());
636 }
637 return none;
638 }
639
646 template <typename F>
647 constexpr auto transform(F&& f) & -> optional<remove_cvref_t<decltype(f(*get_ptr()))>> {
648 if (have_value_) {
649 return _MSTL forward<F>(f)(*get_ptr());
650 }
651 return none;
652 }
653
660 template <typename F>
661 constexpr auto transform(F&& f) const && -> optional<remove_cvref_t<decltype(f(_MSTL move(*get_ptr())))>> {
662 if (have_value_) {
663 return _MSTL forward<F>(f)(_MSTL move(*get_ptr()));
664 }
665 return none;
666 }
667
674 template <typename F>
675 constexpr auto transform(F&& f) && -> optional<remove_cvref_t<decltype(f(_MSTL move(*get_ptr())))>> {
676 if (have_value_) {
677 return _MSTL forward<F>(f)(_MSTL move(*get_ptr()));
678 }
679 return none;
680 }
681
686 constexpr const_pointer operator ->() const noexcept { return get_ptr(); }
687
692 constexpr pointer operator ->() noexcept { return get_ptr(); }
693
698 constexpr const_reference operator *() const & noexcept { return *get_ptr(); }
699
704 constexpr reference operator *() & noexcept { return *get_ptr(); }
705
710 constexpr const value_type&& operator *() const && noexcept { return _MSTL move(*get_ptr()); }
711
716 constexpr value_type&& operator *() && noexcept { return _MSTL move(*get_ptr()); }
717
723 constexpr bool operator ==(const optional& rhs) const noexcept {
724 if (have_value_ != rhs.have_value_) {
725 return false;
726 }
727 if (have_value_) {
728 return *get_ptr() == *rhs.get_ptr();
729 }
730 return true;
731 }
732
738 constexpr bool operator <(const optional& rhs) const noexcept {
739 if (!have_value_ || !rhs.have_value_) {
740 return false;
741 }
742 return *get_ptr() < *rhs.get_ptr();
743 }
744
745 constexpr bool operator ==(none_t) const noexcept { return !have_value_; }
746 constexpr bool operator !=(none_t) const noexcept { return have_value_; }
747 constexpr bool operator >(none_t) const noexcept { return have_value_; }
748 constexpr bool operator <(none_t) const noexcept { return false; }
749 constexpr bool operator >=(none_t) const noexcept { return true; }
750 constexpr bool operator <=(none_t) const noexcept { return !have_value_; }
751
752 friend constexpr bool operator ==(none_t, const optional& rhs) noexcept {
753 return !rhs.have_value_;
754 }
755 friend constexpr bool operator !=(none_t, const optional& rhs) noexcept {
756 return rhs.have_value_;
757 }
758 friend constexpr bool operator >(none_t, const optional&) noexcept {
759 return false;
760 }
761 friend constexpr bool operator <(none_t, const optional& rhs) noexcept {
762 return rhs.have_value_;
763 }
764 friend constexpr bool operator >=(none_t, const optional& rhs) noexcept {
765 return !rhs.have_value_;
766 }
767 friend constexpr bool operator <=(none_t, const optional&) noexcept {
768 return true;
769 }
770
775 constexpr size_t to_hash() const noexcept {
776 return have_value_ ? hash<T>()(*get_ptr()) : _CONSTANTS FNV_OFFSET_BASIS;
777 }
778
783 MSTL_CONSTEXPR20 void swap(optional& other)
784 noexcept(is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>) {
785 if(_MSTL addressof(other) == this) return;
786 if (have_value_ && other.have_value_) {
787 _MSTL swap(*this, other);
788 } else if (have_value_) {
789 other.emplace(_MSTL move(**this));
790 reset();
791 } else if (other.have_value_) {
793 other.reset();
794 }
795 }
796};
797
798
807template <typename T>
809 static_assert(is_object_v<T> && !is_array_v<T>, "optional<T&> requires T to be an object type.");
810
811public:
812 using value_type = T&;
813 using reference = T&;
814 using const_reference = const T&;
815 using pointer = T*;
816 using const_pointer = const T*;
817
818private:
819 T* ptr_ = nullptr;
820
821 template <typename U>
822 using convertible_from_optional_ref = disjunction<
825
826public:
831 constexpr optional(none_t n = none) noexcept {}
832
837 constexpr optional(T& value) noexcept : ptr_(_MSTL addressof(value)) {}
838
844 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
845 constexpr optional(U& value) noexcept : ptr_(_MSTL addressof(value)) {}
846
852 template <typename U, enable_if_t<!is_convertible_v<U&, T&> && is_constructible_v<T&, U&>, int> = 0>
853 constexpr explicit optional(U& value) noexcept : ptr_(_MSTL addressof(value)) {}
854
860 template <typename U, enable_if_t<
861 convertible_from_optional_ref<U>::value, int> = 0>
862 constexpr optional(const _MSTL optional<U&>& other) noexcept : ptr_(other.ptr_) {}
863
869 template <typename U, enable_if_t<
870 !convertible_from_optional_ref<U>::value && is_constructible_v<T&, U&>, int> = 0>
871 constexpr explicit optional(const _MSTL optional<U&>& other) noexcept : ptr_(other.ptr_) {}
872
880 MSTL_CONSTEXPR20 optional& operator =(none_t n) noexcept {
881 ptr_ = nullptr;
882 return *this;
883 }
884
891 template <typename U = T, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
892 MSTL_CONSTEXPR20 optional& operator =(U& value) {
893 if (ptr_) {
894 *ptr_ = value;
895 } else {
896 ptr_ = _MSTL addressof(value);
897 }
898 return *this;
899 }
900
907 template <typename U, enable_if_t<is_assignable_v<T&, U&>, int> = 0>
908 MSTL_CONSTEXPR20 optional& operator =(const _MSTL optional<U&>& other) {
909 if (this != _MSTL addressof(other)) {
910 if (other.ptr_) {
911 if (ptr_) {
912 *ptr_ = *other.ptr_;
913 } else {
914 ptr_ = other.ptr_;
915 }
916 } else {
917 ptr_ = nullptr;
918 }
919 }
920 return *this;
921 }
922
927 constexpr optional(const optional& other) noexcept = default;
928
934 MSTL_CONSTEXPR20 optional& operator =(const optional& other) noexcept = default;
935
940 constexpr optional(optional&& other) noexcept : ptr_(other.ptr_) {}
941
947 MSTL_CONSTEXPR20 optional& operator =(optional&& other) noexcept {
948 ptr_ = other.ptr_;
949 return *this;
950 }
951
952 template <typename... Types>
953 constexpr optional(inplace_construct_tag, Types&&...) = delete;
954
958 ~optional() noexcept {
959 ptr_ = nullptr;
960 }
961
968 template <typename U, enable_if_t<is_convertible_v<U&, T&>, int> = 0>
969 MSTL_CONSTEXPR20 T& emplace(U& value) noexcept {
970 ptr_ = _MSTL 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 MSTL_CONSTEXPR20 T& emplace(U& value) noexcept {
982 ptr_ = _MSTL addressof(value);
983 return *ptr_;
984 }
985
989 MSTL_CONSTEXPR20 void reset() noexcept { ptr_ = nullptr; }
990
994 MSTL_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_) {
1009 throw_exception(optional_exception("optional have no reference"));
1010 }
1011 return *ptr_;
1012 }
1013
1019 constexpr T& value() & {
1020 if (!ptr_) {
1021 throw_exception(optional_exception("optional have no reference"));
1022 }
1023 return *ptr_;
1024 }
1025
1031 constexpr const T&& value() const && {
1032 if (!ptr_) {
1033 throw_exception(optional_exception("optional have no reference"));
1034 }
1035 return *ptr_;
1036 }
1037
1043 constexpr T&& value() && {
1044 if (!ptr_) {
1045 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_) return *ptr_;
1058 return _MSTL forward<U>(value);
1059 }
1060
1066 template <typename U>
1067 constexpr T value_or(U&& value) && {
1068 if (ptr_) return _MSTL move(*ptr_);
1069 return _MSTL forward<U>(value);
1070 }
1071
1078 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1079 constexpr optional or_else(F&& f) const & {
1080 if (ptr_) return *this;
1081 return _MSTL forward<F>(f)();
1082 }
1083
1090 template <typename F, enable_if_t<is_invocable_v<F>, int> = 0>
1091 constexpr optional or_else(F&& f) && {
1092 if (ptr_) return _MSTL move(*this);
1093 return _MSTL forward<F>(f)();
1094 }
1095
1102 template <typename F>
1103 constexpr decltype(auto) and_then(F&& f) const & {
1104 if (ptr_) return _MSTL forward<F>(f)(*ptr_);
1105 return remove_cvref_t<decltype(f(*ptr_))>{};
1106 }
1107
1114 template <typename F>
1115 constexpr decltype(auto) and_then(F&& f) & {
1116 if (ptr_) return _MSTL forward<F>(f)(*ptr_);
1117 return remove_cvref_t<decltype(f(*ptr_))>{};
1118 }
1119
1126 template <typename F>
1127 constexpr decltype(auto) and_then(F&& f) const && {
1128 if (ptr_) return _MSTL forward<F>(f)(_MSTL move(*ptr_));
1129 return remove_cvref_t<decltype(f(*ptr_))>{};
1130 }
1131
1138 template <typename F>
1139 constexpr decltype(auto) and_then(F&& f) && {
1140 if (ptr_) return _MSTL forward<F>(f)(_MSTL move(*ptr_));
1141 return remove_cvref_t<decltype(f(*ptr_))>{};
1142 }
1143
1150 template <typename F>
1151 constexpr auto transform(F&& f) const & -> _MSTL optional<remove_cvref_t<decltype(f(*ptr_))>> {
1152 if (ptr_) return _MSTL forward<F>(f)(*ptr_);
1153 return none;
1154 }
1155
1162 template <typename F>
1163 constexpr auto transform(F&& f) & -> _MSTL optional<remove_cvref_t<decltype(f(*ptr_))>> {
1164 if (ptr_) return _MSTL forward<F>(f)(*ptr_);
1165 return none;
1166 }
1167
1174 template <typename F>
1175 constexpr auto transform(F&& f) const && -> _MSTL optional<remove_cvref_t<decltype(f(*ptr_))>> {
1176 if (ptr_) return _MSTL forward<F>(f)(_MSTL move(*ptr_));
1177 return none;
1178 }
1179
1186 template <typename F>
1187 constexpr auto transform(F&& f) && -> _MSTL optional<remove_cvref_t<decltype(f(*ptr_))>> {
1188 if (ptr_) return _MSTL forward<F>(f)(_MSTL move(*ptr_));
1189 return none;
1190 }
1191
1196 constexpr const T* operator ->() const noexcept { return ptr_; }
1197
1202 constexpr T* operator ->() noexcept { return ptr_; }
1203
1208 constexpr const T& operator *() const & noexcept { return *ptr_; }
1209
1214 constexpr T& operator *() & noexcept { return *ptr_; }
1215
1220 constexpr const T&& operator *() const && noexcept { return *ptr_; }
1221
1226 constexpr T&& operator *() && noexcept { return *ptr_; }
1227
1233 constexpr bool operator ==(const optional& rhs) const noexcept {
1234 if (ptr_ == nullptr || rhs.ptr_ == nullptr) {
1235 return ptr_ == rhs.ptr_;
1236 }
1237 return *ptr_ == *rhs.ptr_;
1238 }
1239
1245 constexpr bool operator <(const optional& rhs) const noexcept {
1246 return ptr_ && rhs.ptr_ && *ptr_ < *rhs.ptr_;
1247 }
1248
1249 constexpr bool operator ==(none_t) const noexcept { return ptr_ == nullptr; }
1250 constexpr bool operator !=(none_t) const noexcept { return ptr_ != nullptr; }
1251 constexpr bool operator >(none_t) const noexcept { return ptr_ != nullptr; }
1252 constexpr bool operator <(none_t) const noexcept { return false; }
1253 constexpr bool operator >=(none_t) const noexcept { return true; }
1254 constexpr bool operator <=(none_t) const noexcept { return ptr_ == nullptr; }
1255
1256 friend constexpr bool operator ==(none_t, const optional& rhs) noexcept {
1257 return rhs.ptr_ == nullptr;
1258 }
1259 friend constexpr bool operator !=(none_t, const optional& rhs) noexcept {
1260 return rhs.ptr_ != nullptr;
1261 }
1262 friend constexpr bool operator >(none_t, const optional&) noexcept {
1263 return false;
1264 }
1265 friend constexpr bool operator <(none_t, const optional& rhs) noexcept {
1266 return rhs.ptr_ != nullptr;
1267 }
1268 friend constexpr bool operator >=(none_t, const optional& rhs) noexcept {
1269 return rhs.ptr_ == nullptr;
1270 }
1271 friend constexpr bool operator <=(none_t, const optional&) noexcept {
1272 return true;
1273 }
1274
1279 constexpr size_t to_hash() const noexcept {
1280 return ptr_ ? hash<remove_cvref_t<T>>()(*ptr_) : _CONSTANTS FNV_OFFSET_BASIS;
1281 }
1282
1287 MSTL_CONSTEXPR20 void swap(optional& other) noexcept {
1288 _MSTL swap(ptr_, other.ptr_);
1289 }
1290};
1291
1292#ifdef MSTL_SUPPORT_DEDUCTION_GUIDES__
1293template <typename T>
1294optional(T) -> optional<T>;
1295#endif
1296
1297
1304template <typename T, enable_if_t<is_constructible_v<decay_t<T>, T>, int> = 0>
1306noexcept(is_nothrow_constructible_v<optional<decay_t<T>>, T>) {
1308}
1309
1317template <typename T, typename... Args, enable_if_t<is_constructible_v<T, Args...>, int> = 0>
1318constexpr optional<T> make_optional(Args&&... args)
1319noexcept(is_nothrow_constructible_v<T, Args...>) {
1321}
1322
1332template <typename T, typename U, typename... Args>
1334optional<T>> make_optional(std::initializer_list<U> ilist, Args&&... args)
1335noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>) {
1336 return optional<T>{ inplace_construct_tag{}, ilist, _MSTL forward<Args>(args)... };
1337}
1338
1345template <typename T>
1346constexpr optional<T&> make_optional(T& value) noexcept {
1347 return optional<T&>{value};
1348}
1349
1353template <typename T>
1355
1356
1364template <typename T>
1365constexpr const T& get(const optional<T>& opt) {
1366 return static_cast<const T&>(static_cast<const optional<T>&>(opt).value());
1367}
1368
1376template <typename T>
1377constexpr T& get(optional<T>& opt) {
1378 return static_cast<T&>(static_cast<optional<T>&>(opt).value());
1379}
1380
1388template <typename T>
1389constexpr const T&& get(const optional<T>&& opt) {
1390 return static_cast<const T&&>(static_cast<const optional<T>&&>(opt).value());
1391}
1392
1400template <typename T>
1401constexpr T&& get(optional<T>&& opt) {
1402 return static_cast<T&&>(static_cast<optional<T>&&>(opt).value());
1403}
1404 // Optional
1406
1408#endif // MSTL_CORE_UTILITY_OPTIONAL_HPP__
const T & const_reference
常量引用类型
constexpr optional(const _MSTL optional< U & > &other) noexcept
从引用可选值隐式转换复制构造
MSTL_CONSTEXPR20 void swap(optional &other) noexcept
交换两个可选值
constexpr T value_or(U &&value) &&
取出存储的引用的移动值
constexpr auto transform(F &&f) const &&-> _MSTL optional< remove_cvref_t< decltype(f(*ptr_))> >
常量右值转换操作
constexpr size_t to_hash() const noexcept
计算哈希值
MSTL_NODISCARD constexpr bool has_value() const noexcept
检查是否持有引用
constexpr optional(U &value) noexcept
从可转换引用隐式转换构造
constexpr T value_or(U &&value) const &
取出存储的引用的拷贝值
MSTL_CONSTEXPR20 void reset() noexcept
重置引用
constexpr auto transform(F &&f) &-> _MSTL optional< remove_cvref_t< decltype(f(*ptr_))> >
左值转换操作
constexpr T & value() &
获取左值引用
constexpr optional(optional &&other) noexcept
移动构造函数
constexpr optional(T &value) noexcept
从引用构造
constexpr const T && value() const &&
获取常量右值引用
T & value_type
值类型
constexpr auto transform(F &&f) const &-> _MSTL optional< remove_cvref_t< decltype(f(*ptr_))> >
常量左值转换操作
constexpr optional(const optional &other) noexcept=default
复制构造函数
constexpr const T & value() const &
获取常量左值引用
T & reference
引用类型
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
T * pointer
指针类型
const T * const_pointer
常量指针类型
~optional() noexcept
析构函数
constexpr auto transform(F &&f) &&-> _MSTL 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 &
常量左值然后操作
MSTL_CONSTEXPR20 T & emplace(U &value) noexcept
隐式转换原位构造引用
constexpr decltype(auto) and_then(F &&f) &
左值然后操作
constexpr decltype(auto) and_then(F &&f) const &&
常量右值然后操作
constexpr optional or_else(F &&f) const &
常量左值否则操作
可选值类
constexpr decltype(auto) and_then(F &&f) &&
右值然后操作
constexpr value_type value_or(value_type value) const &noexcept(is_nothrow_copy_constructible_v< value_type >)
取出存储的值的拷贝值
constexpr auto transform(F &&f) &-> optional< remove_cvref_t< decltype(f(*get_ptr()))> >
左值转换操作
constexpr auto transform(F &&f) &&-> optional< remove_cvref_t< decltype(f(_MSTL move(*get_ptr())))> >
常量右值转换操作
constexpr decltype(auto) and_then(F &&f) const &
常量左值然后操作
constexpr optional(const optional< U & > &other)
从引用可选值赋值
MSTL_CONSTEXPR20 void emplace(Types &&... args) noexcept(is_nothrow_constructible_v< T, Types... >)
原位构造值
constexpr optional(U &&value) noexcept(is_nothrow_constructible_v< T, U >)
从值隐式转换构造
optional(const optional &other)
复制构造函数
constexpr optional(optional< U > &&other) noexcept(is_nothrow_constructible_v< T, U >)
从可选值隐式转换移动构造
constexpr size_t to_hash() const noexcept
计算哈希值
constexpr optional(const optional< U > &other) noexcept(is_nothrow_constructible_v< T, const U & >)
从可选值隐式转换复制构造
MSTL_CONSTEXPR20 void swap(optional &other) noexcept(is_nothrow_move_constructible_v< T > &&is_nothrow_swappable_v< T >)
交换两个可选值
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 >)
取出存储的值的移出值
MSTL_CONSTEXPR20 ~optional() noexcept
析构函数
MSTL_CONSTEXPR20 optional & operator=(none_t n) noexcept
空值赋值运算符
constexpr optional or_else(F &&f) const &
常量左值否则操作
MSTL_NODISCARD constexpr bool has_value() const noexcept
检查是否包含值
constexpr value_type && value() &&
取出存储的值
MSTL_CONSTEXPR20 void emplace(std::initializer_list< U > ilist, Types &&... args) noexcept(is_nothrow_constructible_v< T, std::initializer_list< U > &, Types... >)
使用初始化列表原位构造值
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(inplace_construct_tag, 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 const_reference value() const &
取出存储的值
constexpr auto transform(F &&f) const &&-> optional< remove_cvref_t< decltype(f(_MSTL move(*get_ptr())))> >
右值转换操作
constexpr const value_type && value() const &&
取出存储的值
constexpr reference value() &
取出存储的值
MSTL_CONSTEXPR20 void reset() noexcept
重置可选值为空
optional(optional &&other) noexcept
移动构造函数
MSTL内存构造和销毁函数
MSTL异常处理框架
typename aligned_storage< Len, Align >::type aligned_storage_t
aligned_storage的便捷别名
MSTL_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr duration< _INNER __common_rep_t< Rep1, Rep2 >, Period > operator*(const duration< Rep1, Period > &value, const Rep2 &scalar)
乘法运算符(持续时间 * 标量)
#define MSTL_ERROR_BUILD_FINAL_CLASS(THIS, BASE, INFO)
构建最终异常类宏
bool operator!=(const function< Res(Args...)> &f, nullptr_t null) noexcept
不等于空指针比较
bool operator==(const function< Res(Args...)> &f, nullptr_t null) noexcept
等于空指针比较
MSTL_CONSTEXPR20 enable_if_t< is_constructible_v< T, Args... >, void * > construct(T *ptr, Args &&... args) noexcept(is_nothrow_constructible_v< T, Args... >)
在指定内存位置构造对象
MSTL_CONSTEXPR20 void destroy(T *pointer) noexcept(is_nothrow_destructible_v< T >)
销毁单个对象
#define _MSTL
全局命名空间MSTL前缀
#define _CONSTANTS
constants命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
MSTL_INLINE17 constexpr none_t none
默认空表示
MSTL_NODISCARD constexpr bool operator<=(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于等于比较运算符
MSTL_NODISCARD constexpr bool operator>=(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
大于等于比较运算符
MSTL_NODISCARD constexpr bool operator>(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
大于比较运算符
MSTL_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)
获取可选值中的值
#define MSTL_BUILD_TYPE_ALIAS(TYPE)
快速构建标准类型别名
typename remove_cvref< T >::type remove_cvref_t
remove_cvref的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
void swap()=delete
删除无参数的swap重载
integral_constant< bool, Value > bool_constant
布尔常量包装器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名
MSTL统一调用接口
MSTL空状态类型
类型集合的逻辑或操作
哈希函数的主模板
通用接口,同时具备可比较和可哈希功能
原位构造标签
判断类型是否可以使用指定类型的值进行赋值
判断类型是否可以使用指定参数构造
判断类型From是否可以隐式转换为类型To
空状态类型
optional访问异常