MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
expected.hpp
1#ifndef MSTL_CORE_UTILITY_EXPECTED_HPP__
2#define MSTL_CORE_UTILITY_EXPECTED_HPP__
4#ifdef MSTL_STANDARD_20__
6
7MSTL_ERROR_BUILD_FINAL_CLASS(expected_exception, memory_exception, "Expected Operation Failed.")
8
9struct inplace_invoke_tag {
10 constexpr inplace_invoke_tag() noexcept = default;
11};
12struct unexpect_invoke_tag {
13 constexpr unexpect_invoke_tag() noexcept = default;
14};
15
16struct unexpect_t {
17 explicit unexpect_t() noexcept = default;
18};
19MSTL_INLINE17 constexpr unexpect_t unexpect{};
20
21
22template <typename T, typename ErrorT, typename = void>
23class expected;
24
25template <typename ErrorT>
26class unexpected;
27
28
29template <typename T>
30MSTL_INLINE17 constexpr bool is_expected = false;
31template <typename T, typename ErrorT>
32MSTL_INLINE17 constexpr bool is_expected<expected<T, ErrorT>> = true;
33
34template <typename T>
35MSTL_INLINE17 constexpr bool is_unexpected = false;
36template <typename T>
37MSTL_INLINE17 constexpr bool is_unexpected<unexpected<T>> = true;
38
39
41template <typename Func, typename T>
42using expected_invoke_result = remove_cvref_t<invoke_result_t<Func&&, T&&>>;
43template <typename Func, typename T>
44using expected_transform_result = remove_cv_t<invoke_result_t<Func&&, T&&>>;
45template <typename Func>
46using expected_invoke_narg_result = remove_cvref_t<invoke_result_t<Func&&>>;
47template <typename Func>
48using expected_transform_narg_result = remove_cv_t<invoke_result_t<Func&&>>;
49
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>;
55
56
57template <typename ErrorT>
58class unexpected {
59 static_assert(_INNER can_be_unexpected<ErrorT>, "ErrorT should be non-array, unexpected, const or volatile type");
60
61private:
62 ErrorT error_;
63
64public:
65 constexpr unexpected(const unexpected&) = default;
66 constexpr unexpected(unexpected&&) = default;
67
68 template <typename Err = ErrorT, typename =
70 && !is_same_v<remove_cvref_t<Err>, inplace_construct_tag>
71 && is_constructible_v<ErrorT, Err>>>
72 constexpr explicit
73 unexpected(Err&& error)
74 noexcept(is_nothrow_constructible_v<ErrorT, Err>)
75 : error_(_MSTL forward<Err>(error)) {}
76
77 template <typename... Args, typename =
78 enable_if_t<is_constructible_v<ErrorT, Args...>>>
79 constexpr explicit
80 unexpected(inplace_construct_tag, Args&&... args)
81 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
82 : error_(_MSTL forward<Args>(args)...) {}
83
84 template <typename U, typename... Args, typename =
86 constexpr explicit
87 unexpected(inplace_construct_tag, std::initializer_list<U> list, Args&&... args)
88 noexcept(is_nothrow_constructible_v<ErrorT, std::initializer_list<U>&, Args...>)
89 : error_(list, _MSTL forward<Args>(args)...) {}
90
91 constexpr unexpected& operator =(const unexpected&) = default;
92 constexpr unexpected& operator =(unexpected&&) = default;
93
94 MSTL_NODISCARD constexpr const ErrorT& error() const & noexcept {
95 return error_;
96 }
97
98 MSTL_NODISCARD constexpr ErrorT& error() & noexcept {
99 return error_;
100 }
101
102 MSTL_NODISCARD constexpr const ErrorT&& error() const && noexcept {
103 return _MSTL move(error_);
104 }
105
106 MSTL_NODISCARD constexpr ErrorT&& error() && noexcept {
107 return _MSTL move(error_);
108 }
109
110 constexpr void swap(unexpected& other)
111 noexcept(is_nothrow_swappable_v<ErrorT>) {
112 _MSTL swap(error_, other.error_);
113 }
114
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();
119 }
120};
121
122template <typename ErrorT>
123unexpected(ErrorT) -> unexpected<ErrorT>;
124
125
126template <typename T>
127struct temporary_guard {
128 static_assert(is_nothrow_move_constructible_v<T>);
129
130private:
131 T* guarded_ptr;
132 T temp;
133
134public:
135 constexpr explicit temporary_guard(T& value)
136 : guarded_ptr(_MSTL addressof(value)), temp(_MSTL move(value)) {
137 _MSTL destroy(guarded_ptr);
138 }
139
140 MSTL_CONSTEXPR20 ~temporary_guard() {
141 if (guarded_ptr) MSTL_UNLIKELY {
142 _MSTL construct(guarded_ptr, _MSTL move(temp));
143 }
144 }
145
146 temporary_guard(const temporary_guard&) = delete;
147 temporary_guard& operator =(const temporary_guard&) = delete;
148
149 constexpr T&& release() noexcept {
150 guarded_ptr = nullptr;
151 return _MSTL move(temp);
152 }
153};
154
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>) {
159 _MSTL destroy(old_val);
160 _MSTL construct(new_val, _MSTL forward<Arg>(arg));
161 } else if constexpr (is_nothrow_move_constructible_v<NT>) {
162 NT temp(_MSTL forward<Arg>(arg));
163 _MSTL destroy(old_val);
164 _MSTL construct(new_val, _MSTL move(temp));
165 } else {
166 temporary_guard<OT> guard(*old_val);
167 _MSTL construct(new_val, _MSTL forward<Arg>(arg));
168 guard.release();
169 }
170}
171
172template <typename T, typename ErrorT, typename>
173class expected {
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>);
180
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>>
195 >;
196
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>>
201 >;
202
203 template <typename U>
204 static constexpr bool same_value = is_same_v<typename U::value_type, T>;
205
206 template <typename U>
207 static constexpr bool same_error = is_same_v<typename U::error_type, ErrorT>;
208
209public:
210 using value_type = T;
211 using error_type = ErrorT;
212 using unexpected_type = unexpected<ErrorT>;
213
214 template <typename U>
215 using rebind = expected<U, error_type>;
216
217 constexpr expected()
218 noexcept(is_nothrow_default_constructible_v<T>)
219 : value_(), has_value_(true) {}
220
221 expected(const expected&) = default;
222
223 constexpr expected(const expected& other)
224 noexcept(conjunction_v<
225 is_nothrow_copy_constructible<T>,
226 is_nothrow_copy_constructible<ErrorT>
227 >)
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_) {
233 if (has_value_)
234 _MSTL construct(_MSTL addressof(value_), other.value_);
235 else
236 _MSTL construct(_MSTL addressof(error_), other.error_);
237 }
238
239 expected(expected&&) = default;
240
241 constexpr expected(expected&& other)
242 noexcept(conjunction_v<
243 is_nothrow_move_constructible<T>,
244 is_nothrow_move_constructible<ErrorT>
245 >)
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_) {
249 if (has_value_)
250 _MSTL construct(_MSTL addressof(value_), _MSTL move(other).value_);
251 else
252 _MSTL construct(_MSTL addressof(error_), _MSTL move(other).error_);
253 }
254
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&>
264 >)
265 : has_value_(other.has_value_) {
266 if (has_value_)
267 _MSTL construct(_MSTL addressof(value_), other.value_);
268 else
269 _MSTL construct(_MSTL addressof(error_), other.error_);
270 }
271
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>
281 >)
282 : has_value_(other.has_value_) {
283 if (has_value_)
284 _MSTL construct(_MSTL addressof(value_), _MSTL move(other).value_);
285 else
286 _MSTL construct(_MSTL addressof(error_), _MSTL move(other).error_);
287 }
288
289 template <typename U = T>
290 requires (!is_same_v<remove_cvref_t<U>, expected>)
291 && (!is_same_v<remove_cvref_t<U>, inplace_construct_tag>)
292 && (!is_unexpected<remove_cvref_t<U>>)
293 && is_constructible_v<T, U>
294 constexpr explicit(!is_convertible_v<U, T>)
295 expected(U&& val)
296 noexcept(is_nothrow_constructible_v<T, U>)
297 : value_(_MSTL forward<U>(val)), has_value_(true) {}
298
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) {}
305
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) {}
312
313 template <typename... Args>
314 requires is_constructible_v<T, Args...>
315 constexpr explicit
316 expected(inplace_construct_tag, Args&&... args)
317 noexcept(is_nothrow_constructible_v<T, Args...>)
318 : value_(_MSTL forward<Args>(args)...), has_value_(true) {}
319
320 template <typename U, typename... Args>
321 requires is_constructible_v<T, std::initializer_list<U>&, Args...>
322 constexpr explicit
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) {}
326
327 template <typename... Args>
328 requires is_constructible_v<ErrorT, Args...>
329 constexpr explicit
330 expected(unexpect_t, Args&&... args)
331 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
332 : error_(_MSTL forward<Args>(args)...), has_value_(false) {}
333
334 template <typename U, typename... Args>
335 requires is_constructible_v<ErrorT, std::initializer_list<U>&, Args...>
336 constexpr explicit
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) {}
340
341 constexpr ~expected() = default;
342
343 MSTL_CONSTEXPR20 ~expected()
344 requires (!is_trivially_destructible_v<T>)
345 || (!is_trivially_destructible_v<ErrorT>) {
346 if (has_value_)
347 _MSTL destroy(_MSTL addressof(value_));
348 else
349 _MSTL destroy(_MSTL addressof(error_));
350 }
351
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>
358 >)
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_);
367 else
368 assign_error(other.error_);
369 return *this;
370 }
371
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>
378 >)
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_)
386 assign_value(_MSTL move(other.value_));
387 else
388 assign_error(_MSTL move(other.error_));
389 return *this;
390 }
391
392 template <typename U = T>
393 requires (!is_same_v<expected, remove_cvref_t<U>>)
394 && (!is_unexpected<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) {
401 assign_value(_MSTL forward<U>(val));
402 return *this;
403 }
404
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());
413 return *this;
414 }
415
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) {
423 assign_error(_MSTL move(unex).error());
424 return *this;
425 }
426
427 template <typename... Args>
428 requires is_nothrow_constructible_v<T, Args...>
429 constexpr T& emplace(Args&&... args) noexcept {
430 if (has_value_)
431 _MSTL destroy(_MSTL addressof(value_));
432 else {
433 _MSTL destroy(_MSTL addressof(error_));
434 has_value_ = true;
435 }
437 return value_;
438 }
439
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 {
443 if (has_value_)
444 _MSTL destroy(_MSTL addressof(value_));
445 else {
446 _MSTL destroy(_MSTL addressof(error_));
447 has_value_ = true;
448 }
449 _MSTL construct(_MSTL addressof(value_), list, _MSTL forward<Args>(args)...);
450 return value_;
451 }
452
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&>
459 >)
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>) {
466 if (has_value_) {
467 if (other.has_value_) {
468 using _MSTL swap;
469 swap(value_, other.value_);
470 } else {
471 swap_value_error(other);
472 }
473 } else {
474 if (other.has_value_)
475 other.swap_value_error(*this);
476 else {
477 using _MSTL swap;
478 swap(error_, other.error_);
479 }
480 }
481 }
482
483 MSTL_NODISCARD constexpr const T* operator->() const noexcept {
484 MSTL_CONSTEXPR_ASSERT(has_value_);
485 return _MSTL addressof(value_);
486 }
487
488 MSTL_NODISCARD constexpr T* operator->() noexcept {
489 MSTL_CONSTEXPR_ASSERT(has_value_);
490 return _MSTL addressof(value_);
491 }
492
493 MSTL_NODISCARD constexpr const T& operator*() const & noexcept {
494 MSTL_CONSTEXPR_ASSERT(has_value_);
495 return value_;
496 }
497
498 MSTL_NODISCARD constexpr T& operator*() & noexcept {
499 MSTL_CONSTEXPR_ASSERT(has_value_);
500 return value_;
501 }
502
503 MSTL_NODISCARD constexpr const T&& operator*() const && noexcept {
504 MSTL_CONSTEXPR_ASSERT(has_value_);
505 return _MSTL move(value_);
506 }
507
508 MSTL_NODISCARD constexpr T&& operator*() && noexcept {
509 MSTL_CONSTEXPR_ASSERT(has_value_);
510 return _MSTL move(value_);
511 }
512
513 MSTL_NODISCARD constexpr explicit operator bool() const noexcept {
514 return has_value_;
515 }
516
517 MSTL_NODISCARD constexpr bool has_value() const noexcept {
518 return has_value_;
519 }
520
521 constexpr const T& value() const & {
522 if (has_value_) MSTL_LIKELY
523 return value_;
524 throw_exception(expected_exception(error_));
525 }
526
527 constexpr T& value() & {
528 if (has_value_) MSTL_LIKELY
529 return value_;
530 throw_exception(expected_exception(error_));
531 }
532
533 constexpr const T&& value() const && {
534 if (has_value_) MSTL_LIKELY
535 return _MSTL move(value_);
536 throw_exception(expected_exception(error_));
537 }
538
539 constexpr T&& value() && {
540 if (has_value_) MSTL_LIKELY
541 return _MSTL move(value_);
542 throw_exception(expected_exception(error_));
543 }
544
545 constexpr const ErrorT& error() const & noexcept {
546 MSTL_CONSTEXPR_ASSERT(!has_value_);
547 return error_;
548 }
549
550 constexpr ErrorT& error() & noexcept {
551 MSTL_CONSTEXPR_ASSERT(!has_value_);
552 return error_;
553 }
554
555 constexpr const ErrorT&& error() const && noexcept {
556 MSTL_CONSTEXPR_ASSERT(!has_value_);
557 return _MSTL move(error_);
558 }
559
560 constexpr ErrorT&& error() && noexcept {
561 MSTL_CONSTEXPR_ASSERT(!has_value_);
562 return _MSTL move(error_);
563 }
564
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>
570 >) {
571 static_assert(is_copy_constructible_v<T>);
572 static_assert(is_convertible_v<U, T>);
573
574 if (has_value_)
575 return value_;
576 return static_cast<T>(_MSTL forward<U>(alt));
577 }
578
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>
584 >) {
585 static_assert(is_move_constructible_v<T>);
586 static_assert(is_convertible_v<U, T>);
587
588 if (has_value_)
589 return _MSTL move(value_);
590 return static_cast<T>(_MSTL forward<U>(alt));
591 }
592
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>);
597
598 if (has_value_)
599 return _MSTL forward<Gr>(alt);
600 return error_;
601 }
602
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>);
607
608 if (has_value_)
609 return _MSTL forward<Gr>(alt);
610 return _MSTL move(error_);
611 }
612
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");
621
622 if (has_value())
623 return _MSTL invoke(_MSTL forward<Func>(func), value_);
624 else
625 return Res(unexpect, error_);
626 }
627
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");
636
637 if (has_value())
638 return _MSTL invoke(_MSTL forward<Func>(func), value_);
639 else
640 return Res(unexpect, error_);
641 }
642
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");
651
652 if (has_value())
653 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(value_));
654 else
655 return Res(unexpect, _MSTL move(error_));
656 }
657
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");
666
667 if (has_value())
668 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(value_));
669 else
670 return Res(unexpect, _MSTL move(error_));
671 }
672
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");
681
682 if (has_value())
683 return Res(inplace_construct_tag{}, value_);
684 else
685 return _MSTL invoke(_MSTL forward<Func>(func), error_);
686 }
687
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");
696
697 if (has_value())
698 return Res(inplace_construct_tag{}, value_);
699 else
700 return _MSTL invoke(_MSTL forward<Func>(func), error_);
701 }
702
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");
711
712 if (has_value())
713 return Res(inplace_construct_tag{}, _MSTL move(value_));
714 else
715 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
716 }
717
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");
726
727 if (has_value())
728 return Res(inplace_construct_tag{}, _MSTL move(value_));
729 else
730 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
731 }
732
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>;
738
739 if (has_value())
740 return Res(inplace_invoke_tag{}, [&]() {
741 return _MSTL invoke(_MSTL forward<Func>(func), value_);
742 });
743 else
744 return Res(unexpect, error_);
745 }
746
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>;
752
753 if (has_value())
754 return Res(inplace_invoke_tag{}, [&]() {
755 return _MSTL invoke(_MSTL forward<Func>(func), value_);
756 });
757 else
758 return Res(unexpect, error_);
759 }
760
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>;
766
767 if (has_value())
768 return Res(inplace_invoke_tag{}, [&]() {
769 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(value_));
770 });
771 else
772 return Res(unexpect, _MSTL move(error_));
773 }
774
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>;
780
781 if (has_value())
782 return Res(inplace_invoke_tag{}, [&]() {
783 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(value_));
784 });
785 else
786 return Res(unexpect, _MSTL move(error_));
787 }
788
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>;
794
795 if (has_value())
796 return Res(inplace_construct_tag{}, value_);
797 else
798 return Res(unexpect_invoke_tag{}, [&]() {
799 return _MSTL invoke(_MSTL forward<Func>(func), error_);
800 });
801 }
802
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>;
808
809 if (has_value())
810 return Res(inplace_construct_tag{}, value_);
811 else
812 return Res(unexpect_invoke_tag{}, [&]() {
813 return _MSTL invoke(_MSTL forward<Func>(func), error_);
814 });
815 }
816
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>;
822
823 if (has_value())
824 return Res(inplace_construct_tag{}, _MSTL move(value_));
825 else
826 return Res(unexpect_invoke_tag{}, [&]() {
827 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
828 });
829 }
830
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>;
836
837 if (has_value())
838 return Res(inplace_construct_tag{}, _MSTL move(value_));
839 else
840 return Res(unexpect_invoke_tag{}, [&]() {
841 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
842 });
843 }
844
845 template <typename U, typename Err2>
846 requires (!is_void_v<U>)
847 friend constexpr bool operator==(
848 const expected& lhs,
849 const expected<U, Err2>& rhs) {
850 if (lhs.has_value())
851 return rhs.has_value() && bool(*lhs == *rhs);
852 else
853 return !rhs.has_value() && bool(lhs.error() == rhs.error());
854 }
855
856 template <typename U>
857 friend constexpr bool operator==(const expected& lhs, const U& val) {
858 return lhs.has_value() && bool(*lhs == val);
859 }
860
861 template <typename Err2>
862 friend constexpr bool operator==(
863 const expected& lhs,
864 const unexpected<Err2>& unex) {
865 return !lhs.has_value() && bool(lhs.error() == unex.error());
866 }
867
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); }
872#endif
873 {
874 lhs.swap(rhs);
875 }
876
877private:
878 template <typename, typename, typename> friend class expected;
879
880 template <typename U>
881 constexpr void assign_value(U&& val) {
882 if (has_value_)
883 value_ = _MSTL forward<U>(val);
884 else {
885 reinitialize(_MSTL addressof(value_),
886 _MSTL addressof(error_),
887 _MSTL forward<U>(val));
888 has_value_ = true;
889 }
890 }
891
892 template <typename U>
893 constexpr void assign_error(U&& err) {
894 if (has_value_) {
895 reinitialize(_MSTL addressof(error_),
896 _MSTL addressof(value_),
897 _MSTL forward<U>(err));
898 has_value_ = false;
899 } else {
900 error_ = _MSTL forward<U>(err);
901 }
902 }
903
904 constexpr void swap_value_error(expected& other)
905 noexcept(conjunction_v<
906 is_nothrow_move_constructible<ErrorT>,
907 is_nothrow_move_constructible<T>
908 >) {
909 if constexpr (is_nothrow_move_constructible_v<ErrorT>) {
910 temporary_guard<ErrorT> guard(other.error_);
911 _MSTL construct(_MSTL addressof(other.value_), _MSTL move(value_));
912 other.has_value_ = true;
913 _MSTL destroy(_MSTL addressof(value_));
914 _MSTL construct(_MSTL addressof(error_), guard.release());
915 has_value_ = false;
916 } else {
917 temporary_guard<T> guard(value_);
918 _MSTL construct(_MSTL addressof(error_), _MSTL move(other.error_));
919 has_value_ = false;
920 _MSTL destroy(_MSTL addressof(other.error_));
921 _MSTL construct(_MSTL addressof(other.value_), guard.release());
922 other.has_value_ = true;
923 }
924 }
925
926 template <typename Func>
927 explicit constexpr expected(inplace_invoke_tag, Func&& func)
928 : value_(_MSTL forward<Func>(func)()), has_value_(true) {}
929
930 template <typename Func>
931 explicit constexpr expected(unexpect_invoke_tag, Func&& func)
932 : error_(_MSTL forward<Func>(func)()), has_value_(false) {}
933
934 union {
935 T value_;
936 ErrorT error_;
937 };
938
939 bool has_value_;
940};
941
942template <typename T, typename ErrorT>
943class expected<T, ErrorT, enable_if_t<is_void_v<T>>> {
944 static_assert(_INNER can_be_unexpected<ErrorT>);
945
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>>
952 >;
953
954 template <typename U>
955 static constexpr bool same_value = is_same_v<typename U::value_type, T>;
956
957 template <typename U>
958 static constexpr bool same_error = is_same_v<typename U::error_type, ErrorT>;
959
960 template <typename, typename, typename> friend class expected;
961
962private:
963 union {
964 struct {} void_;
965 ErrorT error_;
966 };
967
968 bool has_value_;
969
970 template <typename U>
971 constexpr void assign_error(U&& err) {
972 if (has_value_) {
974 has_value_ = false;
975 } else {
976 error_ = _MSTL forward<U>(err);
977 }
978 }
979
980 template <typename Func>
981 explicit constexpr expected(inplace_invoke_tag, Func&& func)
982 : void_(), has_value_(true) {
983 _MSTL forward<Func>(func)();
984 }
985
986 template <typename Func>
987 explicit constexpr expected(unexpect_invoke_tag, Func&& func)
988 : error_(_MSTL forward<Func>(func)()), has_value_(false) {}
989
990
991public:
992 using value_type = T;
993 using error_type = ErrorT;
994 using unexpected_type = unexpected<ErrorT>;
995
996 template <typename U>
997 using rebind = expected<U, error_type>;
998
999 constexpr expected() noexcept
1000 : void_(), has_value_(true) {}
1001
1002 expected(const expected&) = default;
1003
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_) {
1009 if (!has_value_)
1010 _MSTL construct(_MSTL addressof(error_), other.error_);
1011 }
1012
1013 expected(expected&&) = default;
1014
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_) {
1020 if (!has_value_)
1021 _MSTL construct(_MSTL addressof(error_), _MSTL move(other).error_);
1022 }
1023
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_) {
1032 if (!has_value_)
1033 _MSTL construct(_MSTL addressof(error_), other.error_);
1034 }
1035
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_) {
1044 if (!has_value_)
1045 _MSTL construct(_MSTL addressof(error_), _MSTL move(other).error_);
1046 }
1047
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) {}
1054
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) {}
1061
1062 constexpr explicit expected(inplace_construct_tag) noexcept
1063 : expected() {}
1064
1065 template <typename... Args>
1066 requires is_constructible_v<ErrorT, Args...>
1067 constexpr explicit
1068 expected(unexpect_t, Args&&... args)
1069 noexcept(is_nothrow_constructible_v<ErrorT, Args...>)
1070 : error_(_MSTL forward<Args>(args)...), has_value_(false) {}
1071
1072 template <typename U, typename... Args>
1073 requires is_constructible_v<ErrorT, std::initializer_list<U>&, Args...>
1074 constexpr explicit
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) {}
1078
1079 MSTL_CONSTEXPR20 ~expected() = default;
1080
1081 MSTL_CONSTEXPR20 ~expected() requires (!is_trivially_destructible_v<ErrorT>) {
1082 if (!has_value_)
1083 _MSTL destroy(_MSTL addressof(error_));
1084 }
1085
1086 constexpr expected& operator =(const expected& other)
1087 noexcept(conjunction_v<
1088 is_nothrow_copy_constructible<ErrorT>,
1089 is_nothrow_copy_assignable<ErrorT>
1090 >)
1091 requires is_copy_constructible_v<ErrorT>
1092 && is_copy_assignable_v<ErrorT> {
1093 if (other.has_value_)
1094 emplace();
1095 else
1096 assign_error(other.error_);
1097 return *this;
1098 }
1099
1100 constexpr expected& operator =(expected&& other)
1101 noexcept(conjunction_v<
1102 is_nothrow_move_constructible<ErrorT>,
1103 is_nothrow_move_assignable<ErrorT>
1104 >)
1105 requires is_move_constructible_v<ErrorT>
1106 && is_move_assignable_v<ErrorT> {
1107 if (other.has_value_)
1108 emplace();
1109 else
1110 assign_error(_MSTL move(other.error_));
1111 return *this;
1112 }
1113
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());
1119 return *this;
1120 }
1121
1122 template <typename Gr>
1123 requires is_constructible_v<ErrorT, Gr>
1124 && is_assignable_v<ErrorT&, Gr>
1125 constexpr expected& operator =(unexpected<Gr>&& unex) {
1126 assign_error(_MSTL move(unex.error()));
1127 return *this;
1128 }
1129
1130 constexpr void emplace() noexcept {
1131 if (!has_value_) {
1132 _MSTL destroy(_MSTL addressof(error_));
1133 has_value_ = true;
1134 }
1135 }
1136
1137 constexpr void swap(expected& other)
1138 noexcept(conjunction_v<
1139 is_nothrow_swappable<ErrorT&>,
1140 is_nothrow_move_constructible<ErrorT>
1141 >)
1142 requires is_swappable_v<ErrorT>
1143 && is_move_constructible_v<ErrorT> {
1144 if (has_value_) {
1145 if (!other.has_value_) {
1146 _MSTL construct(_MSTL addressof(error_), _MSTL move(other.error_));
1147 _MSTL destroy(_MSTL addressof(other.error_));
1148 has_value_ = false;
1149 other.has_value_ = true;
1150 }
1151 } else {
1152 if (other.has_value_) {
1153 _MSTL construct(_MSTL addressof(other.error_), _MSTL move(error_));
1154 _MSTL destroy(_MSTL addressof(error_));
1155 has_value_ = true;
1156 other.has_value_ = false;
1157 } else {
1158 using _MSTL swap;
1159 swap(error_, other.error_);
1160 }
1161 }
1162 }
1163
1164 MSTL_NODISCARD constexpr explicit operator bool() const noexcept {
1165 return has_value_;
1166 }
1167
1168 MSTL_NODISCARD constexpr bool has_value() const noexcept {
1169 return has_value_;
1170 }
1171
1172 constexpr void operator*() const noexcept {
1173 MSTL_CONSTEXPR_ASSERT(has_value_);
1174 }
1175
1176 constexpr void value() const & {
1177 if (has_value_) MSTL_LIKELY
1178 return;
1179 throw_exception(expected_exception(error_));
1180 }
1181
1182 constexpr void value() && {
1183 if (has_value_) MSTL_LIKELY
1184 return;
1185 throw_exception(expected_exception(error_));
1186 }
1187
1188 constexpr const ErrorT& error() const & noexcept {
1189 MSTL_CONSTEXPR_ASSERT(!has_value_);
1190 return error_;
1191 }
1192
1193 constexpr ErrorT& error() & noexcept {
1194 MSTL_CONSTEXPR_ASSERT(!has_value_);
1195 return error_;
1196 }
1197
1198 constexpr const ErrorT&& error() const && noexcept {
1199 MSTL_CONSTEXPR_ASSERT(!has_value_);
1200 return _MSTL move(error_);
1201 }
1202
1203 constexpr ErrorT&& error() && noexcept {
1204 MSTL_CONSTEXPR_ASSERT(!has_value_);
1205 return _MSTL move(error_);
1206 }
1207
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>);
1212
1213 if (has_value_)
1214 return _MSTL forward<Gr>(alt);
1215 return error_;
1216 }
1217
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>);
1222
1223 if (has_value_)
1224 return _MSTL forward<Gr>(alt);
1225 return _MSTL move(error_);
1226 }
1227
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>);
1234
1235 if (has_value())
1236 return _MSTL invoke(_MSTL forward<Func>(func));
1237 else
1238 return Res(unexpect, error_);
1239 }
1240
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>);
1247
1248 if (has_value())
1249 return _MSTL invoke(_MSTL forward<Func>(func));
1250 else
1251 return Res(unexpect, error_);
1252 }
1253
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>);
1260
1261 if (has_value())
1262 return _MSTL invoke(_MSTL forward<Func>(func));
1263 else
1264 return Res(unexpect, _MSTL move(error_));
1265 }
1266
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>);
1273
1274 if (has_value())
1275 return _MSTL invoke(_MSTL forward<Func>(func));
1276 else
1277 return Res(unexpect, _MSTL move(error_));
1278 }
1279
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>);
1285
1286 if (has_value())
1287 return Res();
1288 else
1289 return _MSTL invoke(_MSTL forward<Func>(func), error_);
1290 }
1291
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>);
1297
1298 if (has_value())
1299 return Res();
1300 else
1301 return _MSTL invoke(_MSTL forward<Func>(func), error_);
1302 }
1303
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>);
1309
1310 if (has_value())
1311 return Res();
1312 else
1313 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
1314 }
1315
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>);
1321
1322 if (has_value())
1323 return Res();
1324 else
1325 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
1326 }
1327
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>;
1333
1334 if (has_value())
1335 return Res(inplace_invoke_tag{}, _MSTL forward<Func>(func));
1336 else
1337 return Res(unexpect, error_);
1338 }
1339
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>;
1345
1346 if (has_value())
1347 return Res(inplace_invoke_tag{}, _MSTL forward<Func>(func));
1348 else
1349 return Res(unexpect, error_);
1350 }
1351
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>;
1357
1358 if (has_value())
1359 return Res(inplace_invoke_tag{}, _MSTL forward<Func>(func));
1360 else
1361 return Res(unexpect, _MSTL move(error_));
1362 }
1363
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>;
1369
1370 if (has_value())
1371 return Res(inplace_invoke_tag{}, _MSTL forward<Func>(func));
1372 else
1373 return Res(unexpect, _MSTL move(error_));
1374 }
1375
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>;
1380
1381 if (has_value())
1382 return Res();
1383 else
1384 return Res(unexpect_invoke_tag{}, [&]() {
1385 return _MSTL invoke(_MSTL forward<Func>(func), error_);
1386 });
1387 }
1388
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>;
1393
1394 if (has_value())
1395 return Res();
1396 else
1397 return Res(unexpect_invoke_tag{}, [&]() {
1398 return _MSTL invoke(_MSTL forward<Func>(func), error_);
1399 });
1400 }
1401
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>;
1406
1407 if (has_value())
1408 return Res();
1409 else
1410 return Res(unexpect_invoke_tag{}, [&]() {
1411 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
1412 });
1413 }
1414
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>;
1419
1420 if (has_value())
1421 return Res();
1422 else
1423 return Res(unexpect_invoke_tag{}, [&]() {
1424 return _MSTL invoke(_MSTL forward<Func>(func), _MSTL move(error_));
1425 });
1426 }
1427
1428 template <typename U, typename Err2>
1429 requires is_void_v<U>
1430 friend constexpr bool operator==(
1431 const expected& lhs,
1432 const expected<U, Err2>& rhs) {
1433 if (lhs.has_value())
1434 return rhs.has_value();
1435 else
1436 return !rhs.has_value() && bool(lhs.error() == rhs.error());
1437 }
1438
1439 template <typename Err2>
1440 friend constexpr bool operator==(
1441 const expected& lhs,
1442 const unexpected<Err2>& unex) {
1443 return !lhs.has_value() && bool(lhs.error() == unex.error());
1444 }
1445
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); }
1450#endif
1451 {
1452 lhs.swap(rhs);
1453 }
1454};
1455
1457#endif
1458#endif // MSTL_CORE_UTILITY_EXPECTED_HPP__
MSTL异常处理框架
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的便捷别名
内存操作异常