1#ifndef MSTL_CORE_UTILITY_EXPECTED_HPP__
2#define MSTL_CORE_UTILITY_EXPECTED_HPP__
4#ifdef MSTL_STANDARD_20__
9struct inplace_invoke_tag {
10 constexpr inplace_invoke_tag() noexcept = default;
12struct unexpect_invoke_tag {
13 constexpr unexpect_invoke_tag() noexcept = default;
17 explicit unexpect_t() noexcept = default;
19MSTL_INLINE17 constexpr unexpect_t unexpect{};
22template <
typename T,
typename ErrorT,
typename =
void>
25template <
typename ErrorT>
30MSTL_INLINE17
constexpr bool is_expected =
false;
31template <
typename T,
typename ErrorT>
32MSTL_INLINE17
constexpr bool is_expected<expected<T, ErrorT>> =
true;
35MSTL_INLINE17
constexpr bool is_unexpected =
false;
37MSTL_INLINE17
constexpr bool is_unexpected<unexpected<T>> =
true;
41template <
typename Func,
typename T>
43template <
typename Func,
typename T>
45template <
typename Func>
47template <
typename Func>
50template <
typename ErrorT>
51MSTL_INLINE17
constexpr bool can_be_unexpected = is_object_v<ErrorT>
52 && !is_array_v<ErrorT> && !is_unexpected<ErrorT>
53 && !is_const_v<ErrorT> && !is_volatile_v<ErrorT>;
57template <
typename ErrorT>
59 static_assert(
_INNER can_be_unexpected<ErrorT>,
"ErrorT should be non-array, unexpected, const or volatile type");
65 constexpr unexpected(
const unexpected&) =
default;
66 constexpr unexpected(unexpected&&) =
default;
68 template <
typename Err = ErrorT,
typename =
70 && !is_same_v<remove_cvref_t<Err>, inplace_construct_tag>
71 && is_constructible_v<ErrorT, Err>>>
73 unexpected(Err&& error)
74 noexcept(is_nothrow_constructible_v<ErrorT, Err>)
77 template <
typename... Args,
typename =
80 unexpected(inplace_construct_tag, Args&&... args)
81 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
84 template <
typename U,
typename... Args,
typename =
87 unexpected(inplace_construct_tag, std::initializer_list<U> list, Args&&... args)
88 noexcept(is_nothrow_constructible_v<ErrorT, std::initializer_list<U>&, Args...>)
91 constexpr unexpected& operator =(
const unexpected&) =
default;
92 constexpr unexpected& operator =(unexpected&&) =
default;
94 MSTL_NODISCARD
constexpr const ErrorT& error() const & noexcept {
98 MSTL_NODISCARD
constexpr ErrorT& error() &
noexcept {
102 MSTL_NODISCARD
constexpr const ErrorT&& error() const && noexcept {
106 MSTL_NODISCARD
constexpr ErrorT&& error() &&
noexcept {
110 constexpr void swap(unexpected& other)
111 noexcept(is_nothrow_swappable_v<ErrorT>) {
115 template <
typename OtherError>
116 MSTL_NODISCARD
friend constexpr bool
117 operator==(
const unexpected& lhs,
const unexpected<OtherError>& rhs) {
118 return lhs.error_ == rhs.error();
122template <
typename ErrorT>
123unexpected(ErrorT) -> unexpected<ErrorT>;
127struct temporary_guard {
128 static_assert(is_nothrow_move_constructible_v<T>);
135 constexpr explicit temporary_guard(T& value)
140 MSTL_CONSTEXPR20 ~temporary_guard() {
141 if (guarded_ptr) MSTL_UNLIKELY {
146 temporary_guard(
const temporary_guard&) =
delete;
147 temporary_guard& operator =(
const temporary_guard&) =
delete;
149 constexpr T&&
release() noexcept {
150 guarded_ptr =
nullptr;
155template <
typename NT,
typename OT,
typename Arg>
156constexpr void reinitialize(NT* new_val, OT* old_val, Arg&& arg)
157noexcept(is_nothrow_constructible_v<NT, Arg>) {
158 if constexpr (is_nothrow_constructible_v<NT, Arg>) {
161 }
else if constexpr (is_nothrow_move_constructible_v<NT>) {
166 temporary_guard<OT> guard(*old_val);
172template <
typename T,
typename ErrorT,
typename>
174 static_assert(!is_reference_v<T>);
175 static_assert(!is_function_v<T>);
176 static_assert(!is_same_v<remove_cv_t<T>, inplace_construct_tag>);
177 static_assert(!is_same_v<remove_cv_t<T>, unexpect_t>);
178 static_assert(!is_unexpected<remove_cv_t<T>>);
179 static_assert(
_INNER can_be_unexpected<ErrorT>);
181 template <
typename U,
typename Err,
typename UE = unexpected<ErrorT>>
182 static constexpr bool constructible_from_expected = disjunction_v<
183 is_constructible<T, expected<U, Err>&>,
184 is_constructible<T, expected<U, Err>>,
185 is_constructible<T, const expected<U, Err>&>,
186 is_constructible<T, const expected<U, Err>>,
187 is_convertible<expected<U, Err>&, T>,
188 is_convertible<expected<U, Err>, T>,
189 is_convertible<const expected<U, Err>&, T>,
190 is_convertible<const expected<U, Err>, T>,
191 is_constructible<UE, expected<U, Err>&>,
192 is_constructible<UE, expected<U, Err>>,
193 is_constructible<UE, const expected<U, Err>&>,
194 is_constructible<UE, const expected<U, Err>>
197 template <
typename U,
typename Err>
198 static constexpr bool explicit_conversion = disjunction_v<
199 negation<is_convertible<U, T>>,
200 negation<is_convertible<Err, ErrorT>>
203 template <
typename U>
204 static constexpr bool same_value = is_same_v<typename U::value_type, T>;
206 template <
typename U>
207 static constexpr bool same_error = is_same_v<typename U::error_type, ErrorT>;
210 using value_type = T;
211 using error_type = ErrorT;
212 using unexpected_type = unexpected<ErrorT>;
214 template <
typename U>
215 using rebind = expected<U, error_type>;
218 noexcept(is_nothrow_default_constructible_v<T>)
219 : value_(), has_value_(true) {}
221 expected(
const expected&) =
default;
223 constexpr expected(
const expected& other)
224 noexcept(conjunction_v<
225 is_nothrow_copy_constructible<T>,
226 is_nothrow_copy_constructible<ErrorT>
228 requires is_copy_constructible_v<T>
229 && is_copy_constructible_v<ErrorT>
230 && (!is_trivially_copy_constructible_v<T>
231 || !is_trivially_copy_constructible_v<ErrorT>)
232 : has_value_(other.has_value_) {
239 expected(expected&&) =
default;
241 constexpr expected(expected&& other)
242 noexcept(conjunction_v<
243 is_nothrow_move_constructible<T>,
244 is_nothrow_move_constructible<ErrorT>
246 requires (is_move_constructible_v<T>) && (is_move_constructible_v<ErrorT>)
247 && (!is_trivially_move_constructible_v<T> || !is_trivially_move_constructible_v<ErrorT>)
248 : has_value_(other.has_value_) {
255 template <
typename U,
typename Gr>
256 requires (is_constructible_v<T, const U&>)
257 && (is_constructible_v<ErrorT, const Gr&>)
258 && (!constructible_from_expected<U, Gr>)
259 constexpr explicit(explicit_conversion<const U&, const Gr&>)
260 expected(
const expected<U, Gr>& other)
261 noexcept(conjunction_v<
262 is_nothrow_constructible<T, const U&>,
263 is_nothrow_constructible<ErrorT, const Gr&>
265 : has_value_(other.has_value_) {
272 template <
typename U,
typename Gr>
273 requires is_constructible_v<T, U>
274 && is_constructible_v<ErrorT, Gr>
275 && (!constructible_from_expected<U, Gr>)
276 constexpr explicit(explicit_conversion<U, Gr>)
277 expected(expected<U, Gr>&& other)
278 noexcept(conjunction_v<
279 is_nothrow_constructible<T, U>,
280 is_nothrow_constructible<ErrorT, Gr>
282 : has_value_(other.has_value_) {
289 template <
typename U = T>
290 requires (!is_same_v<remove_cvref_t<U>, expected>)
292 && (!is_unexpected<remove_cvref_t<U>>)
293 && is_constructible_v<T, U>
294 constexpr explicit(!is_convertible_v<U, T>)
296 noexcept(is_nothrow_constructible_v<T, U>)
299 template <
typename Gr = ErrorT>
300 requires is_constructible_v<ErrorT, const Gr&>
301 constexpr explicit(!is_convertible_v<const Gr&, ErrorT>)
302 expected(
const unexpected<Gr>& unex)
303 noexcept(is_nothrow_constructible_v<ErrorT, const Gr&>)
304 : error_(unex.error()), has_value_(false) {}
306 template <
typename Gr = ErrorT>
307 requires is_constructible_v<ErrorT, Gr>
308 constexpr explicit(!is_convertible_v<Gr, ErrorT>)
309 expected(unexpected<Gr>&& unex)
310 noexcept(is_nothrow_constructible_v<ErrorT, Gr>)
311 : error_(
_MSTL move(unex).error()), has_value_(false) {}
313 template <
typename... Args>
314 requires is_constructible_v<T, Args...>
316 expected(inplace_construct_tag, Args&&... args)
317 noexcept(is_nothrow_constructible_v<T, Args...>)
318 : value_(
_MSTL forward<Args>(args)...), has_value_(true) {}
320 template <
typename U,
typename... Args>
321 requires is_constructible_v<T, std::initializer_list<U>&, Args...>
323 expected(inplace_construct_tag, std::initializer_list<U> list, Args&&... args)
324 noexcept(is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>)
325 : value_(list,
_MSTL forward<Args>(args)...), has_value_(true) {}
327 template <
typename... Args>
328 requires is_constructible_v<ErrorT, Args...>
330 expected(unexpect_t, Args&&... args)
331 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
332 : error_(
_MSTL forward<Args>(args)...), has_value_(false) {}
334 template <
typename U,
typename... Args>
335 requires is_constructible_v<ErrorT, std::initializer_list<U>&, Args...>
337 expected(unexpect_t, std::initializer_list<U> list, Args&&... args)
338 noexcept(is_nothrow_constructible_v<ErrorT, std::initializer_list<U>&, Args...>)
339 : error_(list,
_MSTL forward<Args>(args)...), has_value_(false) {}
341 constexpr ~expected() =
default;
343 MSTL_CONSTEXPR20 ~expected()
344 requires (!is_trivially_destructible_v<T>)
345 || (!is_trivially_destructible_v<ErrorT>) {
352 constexpr expected& operator =(
const expected& other)
353 noexcept(conjunction_v<
354 is_nothrow_copy_constructible<T>,
355 is_nothrow_copy_constructible<ErrorT>,
356 is_nothrow_copy_assignable<T>,
357 is_nothrow_copy_assignable<ErrorT>
359 requires is_copy_assignable_v<T>
360 && is_copy_constructible_v<T>
361 && is_copy_assignable_v<ErrorT>
362 && is_copy_constructible_v<ErrorT>
363 && (is_nothrow_move_constructible_v<T>
364 || is_nothrow_move_constructible_v<ErrorT>) {
365 if (other.has_value_)
366 assign_value(other.value_);
368 assign_error(other.error_);
372 constexpr expected& operator =(expected&& other)
373 noexcept(conjunction_v<
374 is_nothrow_move_constructible<T>,
375 is_nothrow_move_constructible<ErrorT>,
376 is_nothrow_move_assignable<T>,
377 is_nothrow_move_assignable<ErrorT>
379 requires is_move_assignable_v<T>
380 && is_move_constructible_v<T>
381 && is_move_assignable_v<ErrorT>
382 && is_move_constructible_v<ErrorT>
383 && (is_nothrow_move_constructible_v<T>
384 || is_nothrow_move_constructible_v<ErrorT>) {
385 if (other.has_value_)
392 template <
typename U = T>
393 requires (!is_same_v<expected, remove_cvref_t<U>>)
395 && is_constructible_v<T, U>
396 && is_assignable_v<T&, U>
397 && (is_nothrow_constructible_v<T, U>
398 || is_nothrow_move_constructible_v<T>
399 || is_nothrow_move_constructible_v<ErrorT>)
400 constexpr expected&
operator =(U&& val) {
405 template <
typename Gr>
406 requires is_constructible_v<ErrorT, const Gr&>
407 && is_assignable_v<ErrorT&, const Gr&>
408 && (is_nothrow_constructible_v<ErrorT, const Gr&>
409 || is_nothrow_move_constructible_v<T>
410 || is_nothrow_move_constructible_v<ErrorT>)
411 constexpr expected&
operator =(
const unexpected<Gr>& unex) {
412 assign_error(unex.error());
416 template <
typename Gr>
417 requires is_constructible_v<ErrorT, Gr>
418 && is_assignable_v<ErrorT&, Gr>
419 && (is_nothrow_constructible_v<ErrorT, Gr>
420 || is_nothrow_move_constructible_v<T>
421 || is_nothrow_move_constructible_v<ErrorT>)
422 constexpr expected&
operator =(unexpected<Gr>&& unex) {
427 template <
typename... Args>
428 requires is_nothrow_constructible_v<T, Args...>
429 constexpr T& emplace(Args&&... args)
noexcept {
440 template <
typename U,
typename... Args>
441 requires is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>
442 constexpr T& emplace(std::initializer_list<U> list, Args&&... args)
noexcept {
453 constexpr void swap(expected& other)
454 noexcept(conjunction_v<
455 is_nothrow_move_constructible<T>,
456 is_nothrow_move_constructible<ErrorT>,
457 is_nothrow_swappable<T&>,
458 is_nothrow_swappable<ErrorT&>
460 requires is_swappable_v<T>
461 && is_swappable_v<ErrorT>
462 && is_move_constructible_v<T>
463 && is_move_constructible_v<ErrorT>
464 && (is_nothrow_move_constructible_v<T>
465 || is_nothrow_move_constructible_v<ErrorT>) {
467 if (other.has_value_) {
469 swap(value_, other.value_);
471 swap_value_error(other);
474 if (other.has_value_)
475 other.swap_value_error(*
this);
478 swap(error_, other.error_);
483 MSTL_NODISCARD
constexpr const T* operator->() const noexcept {
484 MSTL_CONSTEXPR_ASSERT(has_value_);
488 MSTL_NODISCARD
constexpr T* operator->() noexcept {
489 MSTL_CONSTEXPR_ASSERT(has_value_);
493 MSTL_NODISCARD
constexpr const T&
operator*() const & noexcept {
494 MSTL_CONSTEXPR_ASSERT(has_value_);
498 MSTL_NODISCARD
constexpr T&
operator*() &
noexcept {
499 MSTL_CONSTEXPR_ASSERT(has_value_);
503 MSTL_NODISCARD
constexpr const T&&
operator*() const && noexcept {
504 MSTL_CONSTEXPR_ASSERT(has_value_);
508 MSTL_NODISCARD
constexpr T&&
operator*() &&
noexcept {
509 MSTL_CONSTEXPR_ASSERT(has_value_);
513 MSTL_NODISCARD
constexpr explicit operator bool() const noexcept {
517 MSTL_NODISCARD
constexpr bool has_value() const noexcept {
521 constexpr const T& value() const & {
522 if (has_value_) MSTL_LIKELY
524 throw_exception(expected_exception(error_));
527 constexpr T& value() & {
528 if (has_value_) MSTL_LIKELY
530 throw_exception(expected_exception(error_));
533 constexpr const T&& value() const && {
534 if (has_value_) MSTL_LIKELY
536 throw_exception(expected_exception(error_));
539 constexpr T&& value() && {
540 if (has_value_) MSTL_LIKELY
542 throw_exception(expected_exception(error_));
545 constexpr const ErrorT& error() const & noexcept {
546 MSTL_CONSTEXPR_ASSERT(!has_value_);
550 constexpr ErrorT& error() &
noexcept {
551 MSTL_CONSTEXPR_ASSERT(!has_value_);
555 constexpr const ErrorT&& error() const && noexcept {
556 MSTL_CONSTEXPR_ASSERT(!has_value_);
560 constexpr ErrorT&& error() &&
noexcept {
561 MSTL_CONSTEXPR_ASSERT(!has_value_);
565 template <
typename U>
566 constexpr T value_or(U&& alt)
const &
567 noexcept(conjunction_v<
568 is_nothrow_copy_constructible<T>,
569 is_nothrow_convertible<U, T>
571 static_assert(is_copy_constructible_v<T>);
572 static_assert(is_convertible_v<U, T>);
579 template <
typename U>
580 constexpr T value_or(U&& alt) &&
581 noexcept(conjunction_v<
582 is_nothrow_move_constructible<T>,
583 is_nothrow_convertible<U, T>
585 static_assert(is_move_constructible_v<T>);
586 static_assert(is_convertible_v<U, T>);
593 template <
typename Gr = ErrorT>
594 constexpr ErrorT error_or(Gr&& alt)
const & {
595 static_assert(is_copy_constructible_v<ErrorT>);
596 static_assert(is_convertible_v<Gr, ErrorT>);
603 template <
typename Gr = ErrorT>
604 constexpr ErrorT error_or(Gr&& alt) && {
605 static_assert(is_move_constructible_v<ErrorT>);
606 static_assert(is_convertible_v<Gr, ErrorT>);
613 template <
typename Func>
614 requires is_constructible_v<ErrorT, ErrorT&>
615 constexpr auto and_then(Func&& func) & {
616 using Res =
_INNER expected_invoke_result<Func, T&>;
617 static_assert(is_expected<Res>,
618 "Func must return an expected type");
619 static_assert(is_same_v<typename Res::error_type, ErrorT>,
620 "Func must return an expected with same error type");
625 return Res(unexpect, error_);
628 template <
typename Func>
629 requires is_constructible_v<ErrorT, const ErrorT&>
630 constexpr auto and_then(Func&& func)
const & {
631 using Res =
_INNER expected_invoke_result<Func, const T&>;
632 static_assert(is_expected<Res>,
633 "Func must return an expected type");
634 static_assert(is_same_v<typename Res::error_type, ErrorT>,
635 "Func must return an expected with same error type");
640 return Res(unexpect, error_);
643 template <
typename Func>
644 requires is_constructible_v<ErrorT, ErrorT>
645 constexpr auto and_then(Func&& func) && {
646 using Res =
_INNER expected_invoke_result<Func, T&&>;
647 static_assert(is_expected<Res>,
648 "Func must return an expected type");
649 static_assert(is_same_v<typename Res::error_type, ErrorT>,
650 "Func must return an expected with same error type");
655 return Res(unexpect,
_MSTL move(error_));
658 template <
typename Func>
659 requires is_constructible_v<ErrorT, const ErrorT>
660 constexpr auto and_then(Func&& func)
const && {
661 using Res =
_INNER expected_invoke_result<Func, const T&&>;
662 static_assert(is_expected<Res>,
663 "Func must return an expected type");
664 static_assert(is_same_v<typename Res::error_type, ErrorT>,
665 "Func must return an expected with same error type");
670 return Res(unexpect,
_MSTL move(error_));
673 template <
typename Func>
674 requires is_constructible_v<T, T&>
675 constexpr auto or_else(Func&& func) & {
676 using Res =
_INNER expected_invoke_result<Func, ErrorT&>;
677 static_assert(is_expected<Res>,
678 "Func must return an expected type");
679 static_assert(is_same_v<typename Res::value_type, T>,
680 "Func must return an expected with same value type");
683 return Res(inplace_construct_tag{}, value_);
688 template <
typename Func>
689 requires is_constructible_v<T, const T&>
690 constexpr auto or_else(Func&& func)
const & {
691 using Res =
_INNER expected_invoke_result<Func, const ErrorT&>;
692 static_assert(is_expected<Res>,
693 "Func must return an expected type");
694 static_assert(is_same_v<typename Res::value_type, T>,
695 "Func must return an expected with same value type");
698 return Res(inplace_construct_tag{}, value_);
703 template <
typename Func>
704 requires is_constructible_v<T, T>
705 constexpr auto or_else(Func&& func) && {
706 using Res =
_INNER expected_invoke_result<Func, ErrorT&&>;
707 static_assert(is_expected<Res>,
708 "Func must return an expected type");
709 static_assert(is_same_v<typename Res::value_type, T>,
710 "Func must return an expected with same value type");
713 return Res(inplace_construct_tag{},
_MSTL move(value_));
718 template <
typename Func>
719 requires is_constructible_v<T, const T>
720 constexpr auto or_else(Func&& func)
const && {
721 using Res =
_INNER expected_invoke_result<Func, const ErrorT&&>;
722 static_assert(is_expected<Res>,
723 "Func must return an expected type");
724 static_assert(is_same_v<typename Res::value_type, T>,
725 "Func must return an expected with same value type");
728 return Res(inplace_construct_tag{},
_MSTL move(value_));
733 template <
typename Func>
734 requires is_constructible_v<ErrorT, ErrorT&>
735 constexpr auto transform(Func&& func) & {
736 using U =
_INNER expected_transform_result<Func, T&>;
737 using Res = expected<U, ErrorT>;
740 return Res(inplace_invoke_tag{}, [&]() {
744 return Res(unexpect, error_);
747 template <
typename Func>
748 requires is_constructible_v<ErrorT, const ErrorT&>
749 constexpr auto transform(Func&& func)
const & {
750 using U =
_INNER expected_transform_result<Func, const T&>;
751 using Res = expected<U, ErrorT>;
754 return Res(inplace_invoke_tag{}, [&]() {
758 return Res(unexpect, error_);
761 template <
typename Func>
762 requires is_constructible_v<ErrorT, ErrorT>
763 constexpr auto transform(Func&& func) && {
764 using U =
_INNER expected_transform_result<Func, T>;
765 using Res = expected<U, ErrorT>;
768 return Res(inplace_invoke_tag{}, [&]() {
772 return Res(unexpect,
_MSTL move(error_));
775 template <
typename Func>
776 requires is_constructible_v<ErrorT, const ErrorT>
777 constexpr auto transform(Func&& func)
const && {
778 using U =
_INNER expected_transform_result<Func, const T>;
779 using Res = expected<U, ErrorT>;
782 return Res(inplace_invoke_tag{}, [&]() {
786 return Res(unexpect,
_MSTL move(error_));
789 template <
typename Func>
790 requires is_constructible_v<T, T&>
791 constexpr auto transform_error(Func&& func) & {
792 using Gr =
_INNER expected_transform_result<Func, ErrorT&>;
793 using Res = expected<T, Gr>;
796 return Res(inplace_construct_tag{}, value_);
798 return Res(unexpect_invoke_tag{}, [&]() {
803 template <
typename Func>
804 requires is_constructible_v<T, const T&>
805 constexpr auto transform_error(Func&& func)
const & {
806 using Gr =
_INNER expected_transform_result<Func, const ErrorT&>;
807 using Res = expected<T, Gr>;
810 return Res(inplace_construct_tag{}, value_);
812 return Res(unexpect_invoke_tag{}, [&]() {
817 template <
typename Func>
818 requires is_constructible_v<T, T>
819 constexpr auto transform_error(Func&& func) && {
820 using Gr =
_INNER expected_transform_result<Func, ErrorT&&>;
821 using Res = expected<T, Gr>;
824 return Res(inplace_construct_tag{},
_MSTL move(value_));
826 return Res(unexpect_invoke_tag{}, [&]() {
831 template <
typename Func>
832 requires is_constructible_v<T, const T>
833 constexpr auto transform_error(Func&& func)
const && {
834 using Gr =
_INNER expected_transform_result<Func, const ErrorT&&>;
835 using Res = expected<T, Gr>;
838 return Res(inplace_construct_tag{},
_MSTL move(value_));
840 return Res(unexpect_invoke_tag{}, [&]() {
845 template <
typename U,
typename Err2>
846 requires (!is_void_v<U>)
847 friend constexpr bool operator==(
849 const expected<U, Err2>& rhs) {
851 return rhs.has_value() && bool(*lhs == *rhs);
853 return !rhs.has_value() && bool(lhs.error() == rhs.error());
856 template <
typename U>
857 friend constexpr bool operator==(
const expected& lhs,
const U& val) {
858 return lhs.has_value() && bool(*lhs == val);
861 template <
typename Err2>
864 const unexpected<Err2>& unex) {
865 return !lhs.has_value() && bool(lhs.error() == unex.error());
868 friend constexpr void swap(expected& lhs, expected& rhs)
869 noexcept(
noexcept(lhs.swap(rhs)))
870#ifdef MSTL_STANDARD_20__
871 requires requires { lhs.swap(rhs); }
878 template <
typename,
typename,
typename>
friend class expected;
880 template <
typename U>
881 constexpr void assign_value(U&& val) {
892 template <
typename U>
893 constexpr void assign_error(U&& err) {
904 constexpr void swap_value_error(expected& other)
905 noexcept(conjunction_v<
906 is_nothrow_move_constructible<ErrorT>,
907 is_nothrow_move_constructible<T>
909 if constexpr (is_nothrow_move_constructible_v<ErrorT>) {
910 temporary_guard<ErrorT> guard(other.error_);
912 other.has_value_ =
true;
917 temporary_guard<T> guard(value_);
922 other.has_value_ =
true;
926 template <
typename Func>
927 explicit constexpr expected(inplace_invoke_tag, Func&& func)
928 : value_(
_MSTL forward<Func>(func)()), has_value_(true) {}
930 template <
typename Func>
931 explicit constexpr expected(unexpect_invoke_tag, Func&& func)
932 : error_(
_MSTL forward<Func>(func)()), has_value_(false) {}
942template <
typename T,
typename ErrorT>
943class expected<T, ErrorT,
enable_if_t<is_void_v<T>>> {
944 static_assert(
_INNER can_be_unexpected<ErrorT>);
946 template <
typename U,
typename Err,
typename UE = unexpected<ErrorT>>
947 static constexpr bool constructible_from_expected = disjunction_v<
948 is_constructible<UE, expected<U, Err>&>,
949 is_constructible<UE, expected<U, Err>>,
950 is_constructible<UE, const expected<U, Err>&>,
951 is_constructible<UE, const expected<U, Err>>
954 template <
typename U>
955 static constexpr bool same_value = is_same_v<typename U::value_type, T>;
957 template <
typename U>
958 static constexpr bool same_error = is_same_v<typename U::error_type, ErrorT>;
960 template <
typename,
typename,
typename>
friend class expected;
970 template <
typename U>
971 constexpr void assign_error(U&& err) {
980 template <
typename Func>
981 explicit constexpr expected(inplace_invoke_tag, Func&& func)
982 : void_(), has_value_(true) {
986 template <
typename Func>
987 explicit constexpr expected(unexpect_invoke_tag, Func&& func)
988 : error_(
_MSTL forward<Func>(func)()), has_value_(false) {}
992 using value_type = T;
993 using error_type = ErrorT;
994 using unexpected_type = unexpected<ErrorT>;
996 template <
typename U>
997 using rebind = expected<U, error_type>;
999 constexpr expected() noexcept
1000 : void_(), has_value_(true) {}
1002 expected(
const expected&) =
default;
1004 constexpr expected(
const expected& other)
1005 noexcept(is_nothrow_copy_constructible_v<ErrorT>)
1006 requires is_copy_constructible_v<ErrorT>
1007 && (!is_trivially_copy_constructible_v<ErrorT>)
1008 : void_(), has_value_(other.has_value_) {
1013 expected(expected&&) =
default;
1015 constexpr expected(expected&& other)
1016 noexcept(is_nothrow_move_constructible_v<ErrorT>)
1017 requires is_move_constructible_v<ErrorT>
1018 && (!is_trivially_move_constructible_v<ErrorT>)
1019 : void_(), has_value_(other.has_value_) {
1024 template <
typename U,
typename Gr>
1025 requires is_void_v<U>
1026 && is_constructible_v<ErrorT, const Gr&>
1027 && (!constructible_from_expected<U, Gr>)
1028 constexpr explicit(!is_convertible_v<const Gr&, ErrorT>)
1029 expected(
const expected<U, Gr>& other)
1030 noexcept(is_nothrow_constructible_v<ErrorT, const Gr&>)
1031 : void_(), has_value_(other.has_value_) {
1036 template <
typename U,
typename Gr>
1037 requires is_void_v<U>
1038 && is_constructible_v<ErrorT, Gr>
1039 && (!constructible_from_expected<U, Gr>)
1040 constexpr explicit(!is_convertible_v<Gr, ErrorT>)
1041 expected(expected<U, Gr>&& other)
1042 noexcept(is_nothrow_constructible_v<ErrorT, Gr>)
1043 : void_(), has_value_(other.has_value_) {
1048 template <
typename Gr = ErrorT>
1049 requires is_constructible_v<ErrorT, const Gr&>
1050 constexpr explicit(!is_convertible_v<const Gr&, ErrorT>)
1051 expected(
const unexpected<Gr>& unex)
1052 noexcept(is_nothrow_constructible_v<ErrorT, const Gr&>)
1053 : error_(unex.error()), has_value_(false) {}
1055 template <
typename Gr = ErrorT>
1056 requires is_constructible_v<ErrorT, Gr>
1057 constexpr explicit(!is_convertible_v<Gr, ErrorT>)
1058 expected(unexpected<Gr>&& unex)
1059 noexcept(is_nothrow_constructible_v<ErrorT, Gr>)
1060 : error_(
_MSTL move(unex).error()), has_value_(false) {}
1062 constexpr explicit expected(inplace_construct_tag) noexcept
1065 template <
typename... Args>
1066 requires is_constructible_v<ErrorT, Args...>
1068 expected(unexpect_t, Args&&... args)
1069 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
1070 : error_(
_MSTL forward<Args>(args)...), has_value_(false) {}
1072 template <
typename U,
typename... Args>
1073 requires is_constructible_v<ErrorT, std::initializer_list<U>&, Args...>
1075 expected(unexpect_t, std::initializer_list<U> list, Args&&... args)
1076 noexcept(is_nothrow_constructible_v<ErrorT, std::initializer_list<U>&, Args...>)
1077 : error_(list,
_MSTL forward<Args>(args)...), has_value_(false) {}
1079 MSTL_CONSTEXPR20 ~expected() =
default;
1081 MSTL_CONSTEXPR20 ~expected()
requires (!is_trivially_destructible_v<ErrorT>) {
1086 constexpr expected& operator =(
const expected& other)
1087 noexcept(conjunction_v<
1088 is_nothrow_copy_constructible<ErrorT>,
1089 is_nothrow_copy_assignable<ErrorT>
1091 requires is_copy_constructible_v<ErrorT>
1092 && is_copy_assignable_v<ErrorT> {
1093 if (other.has_value_)
1096 assign_error(other.error_);
1100 constexpr expected& operator =(expected&& other)
1101 noexcept(conjunction_v<
1102 is_nothrow_move_constructible<ErrorT>,
1103 is_nothrow_move_assignable<ErrorT>
1105 requires is_move_constructible_v<ErrorT>
1106 && is_move_assignable_v<ErrorT> {
1107 if (other.has_value_)
1114 template <
typename Gr>
1115 requires is_constructible_v<ErrorT, const Gr&>
1116 && is_assignable_v<ErrorT&, const Gr&>
1117 constexpr expected& operator =(
const unexpected<Gr>& unex) {
1118 assign_error(unex.error());
1122 template <
typename Gr>
1123 requires is_constructible_v<ErrorT, Gr>
1124 && is_assignable_v<ErrorT&, Gr>
1125 constexpr expected& operator =(unexpected<Gr>&& unex) {
1130 constexpr void emplace() noexcept {
1137 constexpr void swap(expected& other)
1138 noexcept(conjunction_v<
1139 is_nothrow_swappable<ErrorT&>,
1140 is_nothrow_move_constructible<ErrorT>
1142 requires is_swappable_v<ErrorT>
1143 && is_move_constructible_v<ErrorT> {
1145 if (!other.has_value_) {
1149 other.has_value_ =
true;
1152 if (other.has_value_) {
1156 other.has_value_ =
false;
1159 swap(error_, other.error_);
1164 MSTL_NODISCARD
constexpr explicit operator bool() const noexcept {
1168 MSTL_NODISCARD
constexpr bool has_value() const noexcept {
1172 constexpr void operator*() const noexcept {
1173 MSTL_CONSTEXPR_ASSERT(has_value_);
1176 constexpr void value() const & {
1177 if (has_value_) MSTL_LIKELY
1179 throw_exception(expected_exception(error_));
1182 constexpr void value() && {
1183 if (has_value_) MSTL_LIKELY
1185 throw_exception(expected_exception(error_));
1188 constexpr const ErrorT& error() const & noexcept {
1189 MSTL_CONSTEXPR_ASSERT(!has_value_);
1193 constexpr ErrorT& error() &
noexcept {
1194 MSTL_CONSTEXPR_ASSERT(!has_value_);
1198 constexpr const ErrorT&& error() const && noexcept {
1199 MSTL_CONSTEXPR_ASSERT(!has_value_);
1203 constexpr ErrorT&& error() &&
noexcept {
1204 MSTL_CONSTEXPR_ASSERT(!has_value_);
1208 template <
typename Gr = ErrorT>
1209 constexpr ErrorT error_or(Gr&& alt)
const & {
1210 static_assert(is_copy_constructible_v<ErrorT>);
1211 static_assert(is_convertible_v<Gr, ErrorT>);
1218 template <
typename Gr = ErrorT>
1219 constexpr ErrorT error_or(Gr&& alt) && {
1220 static_assert(is_move_constructible_v<ErrorT>);
1221 static_assert(is_convertible_v<Gr, ErrorT>);
1228 template <
typename Func>
1229 requires is_constructible_v<ErrorT, ErrorT&>
1230 constexpr auto and_then(Func&& func) & {
1231 using Res =
_INNER expected_invoke_narg_result<Func>;
1232 static_assert(is_expected<Res>);
1233 static_assert(is_same_v<typename Res::error_type, ErrorT>);
1238 return Res(unexpect, error_);
1241 template <
typename Func>
1242 requires is_constructible_v<ErrorT, const ErrorT&>
1243 constexpr auto and_then(Func&& func)
const & {
1244 using Res =
_INNER expected_invoke_narg_result<Func>;
1245 static_assert(is_expected<Res>);
1246 static_assert(is_same_v<typename Res::error_type, ErrorT>);
1251 return Res(unexpect, error_);
1254 template <
typename Func>
1255 requires is_constructible_v<ErrorT, ErrorT>
1256 constexpr auto and_then(Func&& func) && {
1257 using Res =
_INNER expected_invoke_narg_result<Func>;
1258 static_assert(is_expected<Res>);
1259 static_assert(is_same_v<typename Res::error_type, ErrorT>);
1264 return Res(unexpect,
_MSTL move(error_));
1267 template <
typename Func>
1268 requires is_constructible_v<ErrorT, const ErrorT>
1269 constexpr auto and_then(Func&& func)
const && {
1270 using Res =
_INNER expected_invoke_narg_result<Func>;
1271 static_assert(is_expected<Res>);
1272 static_assert(is_same_v<typename Res::error_type, ErrorT>);
1277 return Res(unexpect,
_MSTL move(error_));
1280 template <
typename Func>
1281 constexpr auto or_else(Func&& func) & {
1282 using Res =
_INNER expected_invoke_result<Func, ErrorT&>;
1283 static_assert(is_expected<Res>);
1284 static_assert(is_same_v<typename Res::value_type, T>);
1292 template <
typename Func>
1293 constexpr auto or_else(Func&& func)
const & {
1294 using Res =
_INNER expected_invoke_result<Func, const ErrorT&>;
1295 static_assert(is_expected<Res>);
1296 static_assert(is_same_v<typename Res::value_type, T>);
1304 template <
typename Func>
1305 constexpr auto or_else(Func&& func) && {
1306 using Res =
_INNER expected_invoke_result<Func, ErrorT&&>;
1307 static_assert(is_expected<Res>);
1308 static_assert(is_same_v<typename Res::value_type, T>);
1316 template <
typename Func>
1317 constexpr auto or_else(Func&& func)
const && {
1318 using Res =
_INNER expected_invoke_result<Func, const ErrorT&&>;
1319 static_assert(is_expected<Res>);
1320 static_assert(is_same_v<typename Res::value_type, T>);
1328 template <
typename Func>
1329 requires is_constructible_v<ErrorT, ErrorT&>
1330 constexpr auto transform(Func&& func) & {
1331 using U =
_INNER expected_transform_narg_result<Func>;
1332 using Res = expected<U, ErrorT>;
1337 return Res(unexpect, error_);
1340 template <
typename Func>
1341 requires is_constructible_v<ErrorT, const ErrorT&>
1342 constexpr auto transform(Func&& func)
const & {
1343 using U =
_INNER expected_transform_narg_result<Func>;
1344 using Res = expected<U, ErrorT>;
1349 return Res(unexpect, error_);
1352 template <
typename Func>
1353 requires is_constructible_v<ErrorT, ErrorT>
1354 constexpr auto transform(Func&& func) && {
1355 using U =
_INNER expected_transform_narg_result<Func>;
1356 using Res = expected<U, ErrorT>;
1361 return Res(unexpect,
_MSTL move(error_));
1364 template <
typename Func>
1365 requires is_constructible_v<ErrorT, const ErrorT>
1366 constexpr auto transform(Func&& func)
const && {
1367 using U =
_INNER expected_transform_narg_result<Func>;
1368 using Res = expected<U, ErrorT>;
1373 return Res(unexpect,
_MSTL move(error_));
1376 template <
typename Func>
1377 constexpr auto transform_error(Func&& func) & {
1378 using Gr =
_INNER expected_transform_result<Func, ErrorT&>;
1379 using Res = expected<T, Gr>;
1384 return Res(unexpect_invoke_tag{}, [&]() {
1389 template <
typename Func>
1390 constexpr auto transform_error(Func&& func)
const & {
1391 using Gr =
_INNER expected_transform_result<Func, const ErrorT&>;
1392 using Res = expected<T, Gr>;
1397 return Res(unexpect_invoke_tag{}, [&]() {
1402 template <
typename Func>
1403 constexpr auto transform_error(Func&& func) && {
1404 using Gr =
_INNER expected_transform_result<Func, ErrorT&&>;
1405 using Res = expected<T, Gr>;
1410 return Res(unexpect_invoke_tag{}, [&]() {
1415 template <
typename Func>
1416 constexpr auto transform_error(Func&& func)
const && {
1417 using Gr =
_INNER expected_transform_result<Func, const ErrorT&&>;
1418 using Res = expected<T, Gr>;
1423 return Res(unexpect_invoke_tag{}, [&]() {
1428 template <
typename U,
typename Err2>
1429 requires is_void_v<U>
1431 const expected& lhs,
1432 const expected<U, Err2>& rhs) {
1433 if (lhs.has_value())
1434 return rhs.has_value();
1436 return !rhs.has_value() && bool(lhs.error() == rhs.error());
1439 template <
typename Err2>
1441 const expected& lhs,
1442 const unexpected<Err2>& unex) {
1443 return !lhs.has_value() && bool(lhs.error() == unex.error());
1446 friend constexpr void swap(expected& lhs, expected& rhs)
1447 noexcept(
noexcept(lhs.swap(rhs)))
1448#ifdef MSTL_STANDARD_20__
1449 requires requires { lhs.swap(rhs); }
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
等于空指针比较
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 >)
销毁单个对象
MSTL_CONSTEXPR14 _INNER __invoke_result_aux< Callable, Args... >::type invoke(Callable &&f, Args &&... args) noexcept(is_nothrow_invocable< Callable, Args... >::value)
统一调用接口
@ release
释放操作,确保前面的读写不会被重排到后面
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
typename remove_cvref< T >::type remove_cvref_t
remove_cvref的便捷别名
typename remove_cv< T >::type remove_cv_t
remove_cv的便捷别名
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
constexpr Iterator2 transform(Iterator1 first, Iterator1 last, Iterator2 result, UnaryOperation op) noexcept(noexcept(++first) &&noexcept(++result) &&noexcept(*result=op(*first)))
对范围元素应用一元变换
void swap()=delete
删除无参数的swap重载
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名