1// <expected> -*- C++ -*-
3// Copyright The GNU Toolchain Authors.
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
25/** @file include/expected
26 * This is a Standard C++ Library header.
29#ifndef _GLIBCXX_EXPECTED
30#define _GLIBCXX_EXPECTED
32#pragma GCC system_header
34#if __cplusplus > 202002L && __cpp_concepts >= 202002L
36#include <initializer_list>
37#include <bits/exception.h> // exception
38#include <bits/invoke.h> // __invoke
39#include <bits/stl_construct.h> // construct_at
40#include <bits/utility.h> // in_place_t
42namespace std _GLIBCXX_VISIBILITY(default)
44_GLIBCXX_BEGIN_NAMESPACE_VERSION
47 * @defgroup expected_values Expected values
48 * @addtogroup utilities
53#define __cpp_lib_expected 202211L
55 /// Discriminated union that holds an expected value or an error value.
59 template<typename _Tp, typename _Er>
62 /// Wrapper type used to pass an error value to a `std::expected`.
66 template<typename _Er>
69 /// Exception thrown by std::expected when the value() is not present.
73 template<typename _Er>
74 class bad_expected_access;
77 class bad_expected_access<void> : public exception
80 bad_expected_access() noexcept { }
81 bad_expected_access(const bad_expected_access&) = default;
82 bad_expected_access(bad_expected_access&&) = default;
83 bad_expected_access& operator=(const bad_expected_access&) = default;
84 bad_expected_access& operator=(bad_expected_access&&) = default;
85 ~bad_expected_access() = default;
91 what() const noexcept override
92 { return "bad access to std::expected without expected value"; }
95 template<typename _Er>
96 class bad_expected_access : public bad_expected_access<void> {
99 bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
101 // XXX const char* what() const noexcept override;
110 error() const & noexcept
116 { return std::move(_M_unex); }
120 error() const && noexcept
121 { return std::move(_M_unex); }
127 /// Tag type for constructing unexpected values in a std::expected
133 explicit unexpect_t() = default;
136 /// Tag for constructing unexpected values in a std::expected
140 inline constexpr unexpect_t unexpect{};
145 template<typename _Tp>
146 constexpr bool __is_expected = false;
147 template<typename _Tp, typename _Er>
148 constexpr bool __is_expected<expected<_Tp, _Er>> = true;
150 template<typename _Tp>
151 constexpr bool __is_unexpected = false;
152 template<typename _Tp>
153 constexpr bool __is_unexpected<unexpected<_Tp>> = true;
155 template<typename _Fn, typename _Tp>
156 using __result = remove_cvref_t<invoke_result_t<_Fn&&, _Tp&&>>;
157 template<typename _Fn>
158 using __result0 = remove_cvref_t<invoke_result_t<_Fn&&>>;
160 template<typename _Er>
161 concept __can_be_unexpected
162 = is_object_v<_Er> && (!is_array_v<_Er>)
163 && (!__expected::__is_unexpected<_Er>)
164 && (!is_const_v<_Er>) && (!is_volatile_v<_Er>);
166 // Tag types for in-place construction from an invocation result.
167 struct __in_place_inv { };
168 struct __unexpect_inv { };
172 template<typename _Er>
175 static_assert( __expected::__can_be_unexpected<_Er> );
178 constexpr unexpected(const unexpected&) = default;
179 constexpr unexpected(unexpected&&) = default;
181 template<typename _Err = _Er>
182 requires (!is_same_v<remove_cvref_t<_Err>, unexpected>)
183 && (!is_same_v<remove_cvref_t<_Err>, in_place_t>)
184 && is_constructible_v<_Er, _Err>
186 unexpected(_Err&& __e)
187 noexcept(is_nothrow_constructible_v<_Er, _Err>)
188 : _M_unex(std::forward<_Err>(__e))
191 template<typename... _Args>
192 requires is_constructible_v<_Er, _Args...>
194 unexpected(in_place_t, _Args&&... __args)
195 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
196 : _M_unex(std::forward<_Args>(__args)...)
199 template<typename _Up, typename... _Args>
200 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
202 unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
203 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
205 : _M_unex(__il, std::forward<_Args>(__args)...)
208 constexpr unexpected& operator=(const unexpected&) = default;
209 constexpr unexpected& operator=(unexpected&&) = default;
214 error() const & noexcept { return _M_unex; }
218 error() & noexcept { return _M_unex; }
221 constexpr const _Er&&
222 error() const && noexcept { return std::move(_M_unex); }
226 error() && noexcept { return std::move(_M_unex); }
229 swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>)
230 requires is_swappable_v<_Er>
233 swap(_M_unex, __other._M_unex);
236 template<typename _Err>
238 friend constexpr bool
239 operator==(const unexpected& __x, const unexpected<_Err>& __y)
240 { return __x._M_unex == __y.error(); }
242 friend constexpr void
243 swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y)))
244 requires is_swappable_v<_Er>
251 template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
256 template<typename _Tp>
259 static_assert( is_nothrow_move_constructible_v<_Tp> );
263 : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
264 { std::destroy_at(_M_guarded); }
269 if (_M_guarded) [[unlikely]]
270 std::construct_at(_M_guarded, std::move(_M_tmp));
273 _Guard(const _Guard&) = delete;
274 _Guard& operator=(const _Guard&) = delete;
279 _M_guarded = nullptr;
280 return std::move(_M_tmp);
288 // reinit-expected helper from [expected.object.assign]
289 template<typename _Tp, typename _Up, typename _Vp>
291 __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
292 noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
294 if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
296 std::destroy_at(__oldval);
297 std::construct_at(__newval, std::forward<_Vp>(__arg));
299 else if constexpr (is_nothrow_move_constructible_v<_Tp>)
301 _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
302 std::destroy_at(__oldval);
303 std::construct_at(__newval, std::move(__tmp));
307 _Guard<_Up> __guard(*__oldval);
308 std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
315 template<typename _Tp, typename _Er>
318 static_assert( ! is_reference_v<_Tp> );
319 static_assert( ! is_function_v<_Tp> );
320 static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
321 static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
322 static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
323 static_assert( __expected::__can_be_unexpected<_Er> );
325 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
326 static constexpr bool __cons_from_expected
327 = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
328 is_constructible<_Tp, expected<_Up, _Err>>,
329 is_constructible<_Tp, const expected<_Up, _Err>&>,
330 is_constructible<_Tp, const expected<_Up, _Err>>,
331 is_convertible<expected<_Up, _Err>&, _Tp>,
332 is_convertible<expected<_Up, _Err>, _Tp>,
333 is_convertible<const expected<_Up, _Err>&, _Tp>,
334 is_convertible<const expected<_Up, _Err>, _Tp>,
335 is_constructible<_Unex, expected<_Up, _Err>&>,
336 is_constructible<_Unex, expected<_Up, _Err>>,
337 is_constructible<_Unex, const expected<_Up, _Err>&>,
338 is_constructible<_Unex, const expected<_Up, _Err>>
341 template<typename _Up, typename _Err>
342 constexpr static bool __explicit_conv
343 = __or_v<__not_<is_convertible<_Up, _Tp>>,
344 __not_<is_convertible<_Err, _Er>>
347 template<typename _Up>
348 static constexpr bool __same_val
349 = is_same_v<typename _Up::value_type, _Tp>;
351 template<typename _Up>
352 static constexpr bool __same_err
353 = is_same_v<typename _Up::error_type, _Er>;
356 using value_type = _Tp;
357 using error_type = _Er;
358 using unexpected_type = unexpected<_Er>;
360 template<typename _Up>
361 using rebind = expected<_Up, error_type>;
365 noexcept(is_nothrow_default_constructible_v<_Tp>)
366 requires is_default_constructible_v<_Tp>
367 : _M_val(), _M_has_value(true)
370 expected(const expected&) = default;
373 expected(const expected& __x)
374 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
375 is_nothrow_copy_constructible<_Er>>)
376 requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
377 && (!is_trivially_copy_constructible_v<_Tp>
378 || !is_trivially_copy_constructible_v<_Er>)
379 : _M_has_value(__x._M_has_value)
382 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
384 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
387 expected(expected&&) = default;
390 expected(expected&& __x)
391 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
392 is_nothrow_move_constructible<_Er>>)
393 requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
394 && (!is_trivially_move_constructible_v<_Tp>
395 || !is_trivially_move_constructible_v<_Er>)
396 : _M_has_value(__x._M_has_value)
399 std::construct_at(__builtin_addressof(_M_val),
400 std::move(__x)._M_val);
402 std::construct_at(__builtin_addressof(_M_unex),
403 std::move(__x)._M_unex);
406 template<typename _Up, typename _Gr>
407 requires is_constructible_v<_Tp, const _Up&>
408 && is_constructible_v<_Er, const _Gr&>
409 && (!__cons_from_expected<_Up, _Gr>)
410 constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
411 expected(const expected<_Up, _Gr>& __x)
412 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
413 is_nothrow_constructible<_Er, const _Gr&>>)
414 : _M_has_value(__x._M_has_value)
417 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
419 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
422 template<typename _Up, typename _Gr>
423 requires is_constructible_v<_Tp, _Up>
424 && is_constructible_v<_Er, _Gr>
425 && (!__cons_from_expected<_Up, _Gr>)
426 constexpr explicit(__explicit_conv<_Up, _Gr>)
427 expected(expected<_Up, _Gr>&& __x)
428 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
429 is_nothrow_constructible<_Er, _Gr>>)
430 : _M_has_value(__x._M_has_value)
433 std::construct_at(__builtin_addressof(_M_val),
434 std::move(__x)._M_val);
436 std::construct_at(__builtin_addressof(_M_unex),
437 std::move(__x)._M_unex);
440 template<typename _Up = _Tp>
441 requires (!is_same_v<remove_cvref_t<_Up>, expected>)
442 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
443 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
444 && is_constructible_v<_Tp, _Up>
445 constexpr explicit(!is_convertible_v<_Up, _Tp>)
447 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
448 : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
451 template<typename _Gr = _Er>
452 requires is_constructible_v<_Er, const _Gr&>
453 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
454 expected(const unexpected<_Gr>& __u)
455 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
456 : _M_unex(__u.error()), _M_has_value(false)
459 template<typename _Gr = _Er>
460 requires is_constructible_v<_Er, _Gr>
461 constexpr explicit(!is_convertible_v<_Gr, _Er>)
462 expected(unexpected<_Gr>&& __u)
463 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
464 : _M_unex(std::move(__u).error()), _M_has_value(false)
467 template<typename... _Args>
468 requires is_constructible_v<_Tp, _Args...>
470 expected(in_place_t, _Args&&... __args)
471 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
472 : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
475 template<typename _Up, typename... _Args>
476 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
478 expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
479 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
481 : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
484 template<typename... _Args>
485 requires is_constructible_v<_Er, _Args...>
487 expected(unexpect_t, _Args&&... __args)
488 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
489 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
492 template<typename _Up, typename... _Args>
493 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
495 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
496 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
498 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
501 constexpr ~expected() = default;
503 constexpr ~expected()
504 requires (!is_trivially_destructible_v<_Tp>)
505 || (!is_trivially_destructible_v<_Er>)
508 std::destroy_at(__builtin_addressof(_M_val));
510 std::destroy_at(__builtin_addressof(_M_unex));
515 expected& operator=(const expected&) = delete;
518 operator=(const expected& __x)
519 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
520 is_nothrow_copy_constructible<_Er>,
521 is_nothrow_copy_assignable<_Tp>,
522 is_nothrow_copy_assignable<_Er>>)
523 requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
524 && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
525 && (is_nothrow_move_constructible_v<_Tp>
526 || is_nothrow_move_constructible_v<_Er>)
528 if (__x._M_has_value)
529 this->_M_assign_val(__x._M_val);
531 this->_M_assign_unex(__x._M_unex);
536 operator=(expected&& __x)
537 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
538 is_nothrow_move_constructible<_Er>,
539 is_nothrow_move_assignable<_Tp>,
540 is_nothrow_move_assignable<_Er>>)
541 requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
542 && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
543 && (is_nothrow_move_constructible_v<_Tp>
544 || is_nothrow_move_constructible_v<_Er>)
546 if (__x._M_has_value)
547 _M_assign_val(std::move(__x._M_val));
549 _M_assign_unex(std::move(__x._M_unex));
553 template<typename _Up = _Tp>
554 requires (!is_same_v<expected, remove_cvref_t<_Up>>)
555 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
556 && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
557 && (is_nothrow_constructible_v<_Tp, _Up>
558 || is_nothrow_move_constructible_v<_Tp>
559 || is_nothrow_move_constructible_v<_Er>)
563 _M_assign_val(std::forward<_Up>(__v));
567 template<typename _Gr>
568 requires is_constructible_v<_Er, const _Gr&>
569 && is_assignable_v<_Er&, const _Gr&>
570 && (is_nothrow_constructible_v<_Er, const _Gr&>
571 || is_nothrow_move_constructible_v<_Tp>
572 || is_nothrow_move_constructible_v<_Er>)
574 operator=(const unexpected<_Gr>& __e)
576 _M_assign_unex(__e.error());
580 template<typename _Gr>
581 requires is_constructible_v<_Er, _Gr>
582 && is_assignable_v<_Er&, _Gr>
583 && (is_nothrow_constructible_v<_Er, _Gr>
584 || is_nothrow_move_constructible_v<_Tp>
585 || is_nothrow_move_constructible_v<_Er>)
587 operator=(unexpected<_Gr>&& __e)
589 _M_assign_unex(std::move(__e).error());
595 template<typename... _Args>
596 requires is_nothrow_constructible_v<_Tp, _Args...>
598 emplace(_Args&&... __args) noexcept
601 std::destroy_at(__builtin_addressof(_M_val));
604 std::destroy_at(__builtin_addressof(_M_unex));
607 std::construct_at(__builtin_addressof(_M_val),
608 std::forward<_Args>(__args)...);
612 template<typename _Up, typename... _Args>
613 requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
616 emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
619 std::destroy_at(__builtin_addressof(_M_val));
622 std::destroy_at(__builtin_addressof(_M_unex));
625 std::construct_at(__builtin_addressof(_M_val),
626 __il, std::forward<_Args>(__args)...);
633 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
634 is_nothrow_move_constructible<_Er>,
635 is_nothrow_swappable<_Tp&>,
636 is_nothrow_swappable<_Er&>>)
637 requires is_swappable_v<_Tp> && is_swappable_v<_Er>
638 && is_move_constructible_v<_Tp>
639 && is_move_constructible_v<_Er>
640 && (is_nothrow_move_constructible_v<_Tp>
641 || is_nothrow_move_constructible_v<_Er>)
645 if (__x._M_has_value)
648 swap(_M_val, __x._M_val);
651 this->_M_swap_val_unex(__x);
655 if (__x._M_has_value)
656 __x._M_swap_val_unex(*this);
660 swap(_M_unex, __x._M_unex);
669 operator->() const noexcept
671 __glibcxx_assert(_M_has_value);
672 return __builtin_addressof(_M_val);
677 operator->() noexcept
679 __glibcxx_assert(_M_has_value);
680 return __builtin_addressof(_M_val);
685 operator*() const & noexcept
687 __glibcxx_assert(_M_has_value);
693 operator*() & noexcept
695 __glibcxx_assert(_M_has_value);
700 constexpr const _Tp&&
701 operator*() const && noexcept
703 __glibcxx_assert(_M_has_value);
704 return std::move(_M_val);
709 operator*() && noexcept
711 __glibcxx_assert(_M_has_value);
712 return std::move(_M_val);
717 operator bool() const noexcept { return _M_has_value; }
720 constexpr bool has_value() const noexcept { return _M_has_value; }
725 if (_M_has_value) [[likely]]
727 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
733 if (_M_has_value) [[likely]]
735 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
738 constexpr const _Tp&&
741 if (_M_has_value) [[likely]]
742 return std::move(_M_val);
743 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
744 std::move(_M_unex)));
750 if (_M_has_value) [[likely]]
751 return std::move(_M_val);
752 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
753 std::move(_M_unex)));
757 error() const & noexcept
759 __glibcxx_assert(!_M_has_value);
766 __glibcxx_assert(!_M_has_value);
770 constexpr const _Er&&
771 error() const && noexcept
773 __glibcxx_assert(!_M_has_value);
774 return std::move(_M_unex);
780 __glibcxx_assert(!_M_has_value);
781 return std::move(_M_unex);
784 template<typename _Up>
786 value_or(_Up&& __v) const &
787 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
788 is_nothrow_convertible<_Up, _Tp>>)
790 static_assert( is_copy_constructible_v<_Tp> );
791 static_assert( is_convertible_v<_Up, _Tp> );
795 return static_cast<_Tp>(std::forward<_Up>(__v));
798 template<typename _Up>
800 value_or(_Up&& __v) &&
801 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
802 is_nothrow_convertible<_Up, _Tp>>)
804 static_assert( is_move_constructible_v<_Tp> );
805 static_assert( is_convertible_v<_Up, _Tp> );
808 return std::move(_M_val);
809 return static_cast<_Tp>(std::forward<_Up>(__v));
812 template<typename _Gr = _Er>
814 error_or(_Gr&& __e) const&
816 static_assert( is_copy_constructible_v<_Er> );
817 static_assert( is_convertible_v<_Gr, _Er> );
820 return std::forward<_Gr>(__e);
824 template<typename _Gr = _Er>
826 error_or(_Gr&& __e) &&
828 static_assert( is_move_constructible_v<_Er> );
829 static_assert( is_convertible_v<_Gr, _Er> );
832 return std::forward<_Gr>(__e);
833 return std::move(_M_unex);
836 // monadic operations
838 template<typename _Fn> requires is_copy_constructible_v<_Er>
840 and_then(_Fn&& __f) &
842 using _Up = __expected::__result<_Fn, _Tp&>;
843 static_assert(__expected::__is_expected<_Up>);
844 static_assert(is_same_v<typename _Up::error_type, _Er>);
847 return std::__invoke(std::forward<_Fn>(__f), value());
849 return _Up(unexpect, error());
852 template<typename _Fn> requires is_copy_constructible_v<_Er>
854 and_then(_Fn&& __f) const &
856 using _Up = __expected::__result<_Fn, const _Tp&>;
857 static_assert(__expected::__is_expected<_Up>);
858 static_assert(is_same_v<typename _Up::error_type, _Er>);
861 return std::__invoke(std::forward<_Fn>(__f), value());
863 return _Up(unexpect, error());
866 template<typename _Fn> requires is_move_constructible_v<_Er>
868 and_then(_Fn&& __f) &&
870 using _Up = __expected::__result<_Fn, _Tp&&>;
871 static_assert(__expected::__is_expected<_Up>);
872 static_assert(is_same_v<typename _Up::error_type, _Er>);
875 return std::__invoke(std::forward<_Fn>(__f), std::move(value()));
877 return _Up(unexpect, std::move(error()));
881 template<typename _Fn> requires is_move_constructible_v<_Er>
883 and_then(_Fn&& __f) const &&
885 using _Up = __expected::__result<_Fn, const _Tp&&>;
886 static_assert(__expected::__is_expected<_Up>);
887 static_assert(is_same_v<typename _Up::error_type, _Er>);
890 return std::__invoke(std::forward<_Fn>(__f), std::move(value()));
892 return _Up(unexpect, std::move(error()));
895 template<typename _Fn> requires is_copy_constructible_v<_Er>
899 using _Gr = __expected::__result<_Fn, _Er&>;
900 static_assert(__expected::__is_expected<_Gr>);
901 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
904 return _Gr(in_place, value());
906 return std::__invoke(std::forward<_Fn>(__f), error());
909 template<typename _Fn> requires is_copy_constructible_v<_Er>
911 or_else(_Fn&& __f) const &
913 using _Gr = __expected::__result<_Fn, const _Er&>;
914 static_assert(__expected::__is_expected<_Gr>);
915 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
918 return _Gr(in_place, value());
920 return std::__invoke(std::forward<_Fn>(__f), error());
924 template<typename _Fn> requires is_move_constructible_v<_Er>
926 or_else(_Fn&& __f) &&
928 using _Gr = __expected::__result<_Fn, _Er&&>;
929 static_assert(__expected::__is_expected<_Gr>);
930 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
933 return _Gr(in_place, std::move(value()));
935 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
938 template<typename _Fn> requires is_move_constructible_v<_Er>
940 or_else(_Fn&& __f) const &&
942 using _Gr = __expected::__result<_Fn, const _Er&&>;
943 static_assert(__expected::__is_expected<_Gr>);
944 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
947 return _Gr(in_place, std::move(value()));
949 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
952 template<typename _Fn> requires is_copy_constructible_v<_Er>
954 transform(_Fn&& __f) &
956 using _Up = __expected::__result<_Fn, _Tp&>;
957 using _Res = expected<_Up, _Er>;
960 return _Res(__in_place_inv{}, [&]() {
961 return std::__invoke(std::forward<_Fn>(__f),
965 return _Res(unexpect, std::move(error()));
968 template<typename _Fn> requires is_copy_constructible_v<_Er>
970 transform(_Fn&& __f) const &
972 using _Up = __expected::__result<_Fn, const _Tp&>;
973 using _Res = expected<_Up, _Er>;
976 return _Res(__in_place_inv{}, [&]() {
977 return std::__invoke(std::forward<_Fn>(__f),
981 return _Res(unexpect, std::move(error()));
984 template<typename _Fn> requires is_move_constructible_v<_Er>
986 transform(_Fn&& __f) &&
988 using _Up = __expected::__result<_Fn, _Tp>;
989 using _Res = expected<_Up, _Er>;
992 return _Res(__in_place_inv{}, [&]() {
993 return std::__invoke(std::forward<_Fn>(__f),
997 return _Res(unexpect, std::move(error()));
1000 template<typename _Fn> requires is_move_constructible_v<_Er>
1002 transform(_Fn&& __f) const &&
1004 using _Up = __expected::__result<_Fn, const _Tp>;
1005 using _Res = expected<_Up, _Er>;
1008 return _Res(__in_place_inv{}, [&]() {
1009 return std::__invoke(std::forward<_Fn>(__f),
1013 return _Res(unexpect, std::move(error()));
1016 template<typename _Fn> requires is_copy_constructible_v<_Tp>
1018 transform_error(_Fn&& __f) &
1020 using _Gr = __expected::__result<_Fn, _Er&>;
1021 using _Res = expected<_Tp, _Gr>;
1024 return _Res(in_place, value());
1026 return _Res(__unexpect_inv{}, [&]() {
1027 return std::__invoke(std::forward<_Fn>(__f),
1032 template<typename _Fn> requires is_copy_constructible_v<_Tp>
1034 transform_error(_Fn&& __f) const &
1036 using _Gr = __expected::__result<_Fn, const _Er&>;
1037 using _Res = expected<_Tp, _Gr>;
1040 return _Res(in_place, value());
1042 return _Res(__unexpect_inv{}, [&]() {
1043 return std::__invoke(std::forward<_Fn>(__f),
1048 template<typename _Fn> requires is_move_constructible_v<_Tp>
1050 transform_error(_Fn&& __f) &&
1052 using _Gr = __expected::__result<_Fn, _Er&&>;
1053 using _Res = expected<_Tp, _Gr>;
1056 return _Res(in_place, std::move(value()));
1058 return _Res(__unexpect_inv{}, [&]() {
1059 return std::__invoke(std::forward<_Fn>(__f),
1060 std::move(_M_unex));
1064 template<typename _Fn> requires is_move_constructible_v<_Tp>
1066 transform_error(_Fn&& __f) const &&
1068 using _Gr = __expected::__result<_Fn, const _Er&&>;
1069 using _Res = expected<_Tp, _Gr>;
1072 return _Res(in_place, std::move(value()));
1074 return _Res(__unexpect_inv{}, [&]() {
1075 return std::__invoke(std::forward<_Fn>(__f),
1076 std::move(_M_unex));
1080 // equality operators
1082 template<typename _Up, typename _Er2>
1083 requires (!is_void_v<_Up>)
1084 friend constexpr bool
1085 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1086 // FIXME: noexcept(noexcept(bool(*__x == *__y))
1087 // && noexcept(bool(__x.error() == __y.error())))
1089 if (__x.has_value())
1090 return __y.has_value() && bool(*__x == *__y);
1092 return !__y.has_value() && bool(__x.error() == __y.error());
1095 template<typename _Up>
1096 friend constexpr bool
1097 operator==(const expected& __x, const _Up& __v)
1098 // FIXME: noexcept(noexcept(bool(*__x == __v)))
1099 { return __x.has_value() && bool(*__x == __v); }
1101 template<typename _Er2>
1102 friend constexpr bool
1103 operator==(const expected& __x, const unexpected<_Er2>& __e)
1104 // FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
1105 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1107 friend constexpr void
1108 swap(expected& __x, expected& __y)
1109 noexcept(noexcept(__x.swap(__y)))
1110 requires requires {__x.swap(__y);}
1114 template<typename, typename> friend class expected;
1116 template<typename _Vp>
1118 _M_assign_val(_Vp&& __v)
1121 _M_val = std::forward<_Vp>(__v);
1124 __expected::__reinit(__builtin_addressof(_M_val),
1125 __builtin_addressof(_M_unex),
1126 std::forward<_Vp>(__v));
1127 _M_has_value = true;
1131 template<typename _Vp>
1133 _M_assign_unex(_Vp&& __v)
1137 __expected::__reinit(__builtin_addressof(_M_unex),
1138 __builtin_addressof(_M_val),
1139 std::forward<_Vp>(__v));
1140 _M_has_value = false;
1143 _M_unex = std::forward<_Vp>(__v);
1146 // Swap two expected objects when only one has a value.
1147 // Precondition: this->_M_has_value && !__rhs._M_has_value
1149 _M_swap_val_unex(expected& __rhs)
1150 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1151 is_nothrow_move_constructible<_Tp>>)
1153 if constexpr (is_nothrow_move_constructible_v<_Er>)
1155 __expected::_Guard<_Er> __guard(__rhs._M_unex);
1156 std::construct_at(__builtin_addressof(__rhs._M_val),
1157 std::move(_M_val)); // might throw
1158 __rhs._M_has_value = true;
1159 std::destroy_at(__builtin_addressof(_M_val));
1160 std::construct_at(__builtin_addressof(_M_unex),
1162 _M_has_value = false;
1166 __expected::_Guard<_Tp> __guard(_M_val);
1167 std::construct_at(__builtin_addressof(_M_unex),
1168 std::move(__rhs._M_unex)); // might throw
1169 _M_has_value = false;
1170 std::destroy_at(__builtin_addressof(__rhs._M_unex));
1171 std::construct_at(__builtin_addressof(__rhs._M_val),
1173 __rhs._M_has_value = true;
1177 using __in_place_inv = __expected::__in_place_inv;
1178 using __unexpect_inv = __expected::__unexpect_inv;
1180 template<typename _Fn>
1182 expected(__in_place_inv, _Fn&& __fn)
1183 : _M_val(std::forward<_Fn>(__fn)()), _M_has_value(true)
1186 template<typename _Fn>
1188 expected(__unexpect_inv, _Fn&& __fn)
1189 : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
1200 // Partial specialization for std::expected<cv void, E>
1201 template<typename _Tp, typename _Er> requires is_void_v<_Tp>
1202 class expected<_Tp, _Er>
1204 static_assert( __expected::__can_be_unexpected<_Er> );
1206 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
1207 static constexpr bool __cons_from_expected
1208 = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
1209 is_constructible<_Unex, expected<_Up, _Err>>,
1210 is_constructible<_Unex, const expected<_Up, _Err>&>,
1211 is_constructible<_Unex, const expected<_Up, _Err>>
1214 template<typename _Up>
1215 static constexpr bool __same_val
1216 = is_same_v<typename _Up::value_type, _Tp>;
1218 template<typename _Up>
1219 static constexpr bool __same_err
1220 = is_same_v<typename _Up::error_type, _Er>;
1223 using value_type = _Tp;
1224 using error_type = _Er;
1225 using unexpected_type = unexpected<_Er>;
1227 template<typename _Up>
1228 using rebind = expected<_Up, error_type>;
1232 : _M_void(), _M_has_value(true)
1235 expected(const expected&) = default;
1238 expected(const expected& __x)
1239 noexcept(is_nothrow_copy_constructible_v<_Er>)
1240 requires is_copy_constructible_v<_Er>
1241 && (!is_trivially_copy_constructible_v<_Er>)
1242 : _M_void(), _M_has_value(__x._M_has_value)
1245 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
1248 expected(expected&&) = default;
1251 expected(expected&& __x)
1252 noexcept(is_nothrow_move_constructible_v<_Er>)
1253 requires is_move_constructible_v<_Er>
1254 && (!is_trivially_move_constructible_v<_Er>)
1255 : _M_void(), _M_has_value(__x._M_has_value)
1258 std::construct_at(__builtin_addressof(_M_unex),
1259 std::move(__x)._M_unex);
1262 template<typename _Up, typename _Gr>
1263 requires is_void_v<_Up>
1264 && is_constructible_v<_Er, const _Gr&>
1265 && (!__cons_from_expected<_Up, _Gr>)
1266 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
1267 expected(const expected<_Up, _Gr>& __x)
1268 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
1269 : _M_void(), _M_has_value(__x._M_has_value)
1272 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
1275 template<typename _Up, typename _Gr>
1276 requires is_void_v<_Up>
1277 && is_constructible_v<_Er, _Gr>
1278 && (!__cons_from_expected<_Up, _Gr>)
1279 constexpr explicit(!is_convertible_v<_Gr, _Er>)
1280 expected(expected<_Up, _Gr>&& __x)
1281 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
1282 : _M_void(), _M_has_value(__x._M_has_value)
1285 std::construct_at(__builtin_addressof(_M_unex),
1286 std::move(__x)._M_unex);
1289 template<typename _Gr = _Er>
1290 requires is_constructible_v<_Er, const _Gr&>
1291 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
1292 expected(const unexpected<_Gr>& __u)
1293 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
1294 : _M_unex(__u.error()), _M_has_value(false)
1297 template<typename _Gr = _Er>
1298 requires is_constructible_v<_Er, _Gr>
1299 constexpr explicit(!is_convertible_v<_Gr, _Er>)
1300 expected(unexpected<_Gr>&& __u)
1301 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
1302 : _M_unex(std::move(__u).error()), _M_has_value(false)
1306 expected(in_place_t) noexcept
1310 template<typename... _Args>
1311 requires is_constructible_v<_Er, _Args...>
1313 expected(unexpect_t, _Args&&... __args)
1314 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1315 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1318 template<typename _Up, typename... _Args>
1319 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1321 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1322 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1324 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1327 constexpr ~expected() = default;
1329 constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1332 std::destroy_at(__builtin_addressof(_M_unex));
1337 expected& operator=(const expected&) = delete;
1340 operator=(const expected& __x)
1341 noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1342 is_nothrow_copy_assignable<_Er>>)
1343 requires is_copy_constructible_v<_Er>
1344 && is_copy_assignable_v<_Er>
1346 if (__x._M_has_value)
1349 _M_assign_unex(__x._M_unex);
1354 operator=(expected&& __x)
1355 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1356 is_nothrow_move_assignable<_Er>>)
1357 requires is_move_constructible_v<_Er>
1358 && is_move_assignable_v<_Er>
1360 if (__x._M_has_value)
1363 _M_assign_unex(std::move(__x._M_unex));
1367 template<typename _Gr>
1368 requires is_constructible_v<_Er, const _Gr&>
1369 && is_assignable_v<_Er&, const _Gr&>
1371 operator=(const unexpected<_Gr>& __e)
1373 _M_assign_unex(__e.error());
1377 template<typename _Gr>
1378 requires is_constructible_v<_Er, _Gr>
1379 && is_assignable_v<_Er&, _Gr>
1381 operator=(unexpected<_Gr>&& __e)
1383 _M_assign_unex(std::move(__e.error()));
1394 std::destroy_at(__builtin_addressof(_M_unex));
1395 _M_has_value = true;
1402 noexcept(__and_v<is_nothrow_swappable<_Er&>,
1403 is_nothrow_move_constructible<_Er>>)
1404 requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1408 if (!__x._M_has_value)
1410 std::construct_at(__builtin_addressof(_M_unex),
1411 std::move(__x._M_unex)); // might throw
1412 std::destroy_at(__builtin_addressof(__x._M_unex));
1413 _M_has_value = false;
1414 __x._M_has_value = true;
1419 if (__x._M_has_value)
1421 std::construct_at(__builtin_addressof(__x._M_unex),
1422 std::move(_M_unex)); // might throw
1423 std::destroy_at(__builtin_addressof(_M_unex));
1424 _M_has_value = true;
1425 __x._M_has_value = false;
1430 swap(_M_unex, __x._M_unex);
1439 operator bool() const noexcept { return _M_has_value; }
1442 constexpr bool has_value() const noexcept { return _M_has_value; }
1445 operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1450 if (_M_has_value) [[likely]]
1452 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1458 if (_M_has_value) [[likely]]
1460 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1463 constexpr const _Er&
1464 error() const & noexcept
1466 __glibcxx_assert(!_M_has_value);
1473 __glibcxx_assert(!_M_has_value);
1477 constexpr const _Er&&
1478 error() const && noexcept
1480 __glibcxx_assert(!_M_has_value);
1481 return std::move(_M_unex);
1487 __glibcxx_assert(!_M_has_value);
1488 return std::move(_M_unex);
1491 template<typename _Gr = _Er>
1493 error_or(_Gr&& __e) const&
1495 static_assert( is_copy_constructible_v<_Er> );
1496 static_assert( is_convertible_v<_Gr, _Er> );
1499 return std::forward<_Gr>(__e);
1503 template<typename _Gr = _Er>
1505 error_or(_Gr&& __e) &&
1507 static_assert( is_move_constructible_v<_Er> );
1508 static_assert( is_convertible_v<_Gr, _Er> );
1511 return std::forward<_Gr>(__e);
1512 return std::move(_M_unex);
1515 // monadic operations
1517 template<typename _Fn> requires is_copy_constructible_v<_Er>
1519 and_then(_Fn&& __f) &
1521 using _Up = __expected::__result0<_Fn>;
1522 static_assert(__expected::__is_expected<_Up>);
1523 static_assert(is_same_v<typename _Up::error_type, _Er>);
1526 return std::__invoke(std::forward<_Fn>(__f));
1528 return _Up(unexpect, error());
1531 template<typename _Fn> requires is_copy_constructible_v<_Er>
1533 and_then(_Fn&& __f) const &
1535 using _Up = __expected::__result0<_Fn>;
1536 static_assert(__expected::__is_expected<_Up>);
1537 static_assert(is_same_v<typename _Up::error_type, _Er>);
1540 return std::__invoke(std::forward<_Fn>(__f));
1542 return _Up(unexpect, error());
1545 template<typename _Fn> requires is_move_constructible_v<_Er>
1547 and_then(_Fn&& __f) &&
1549 using _Up = __expected::__result0<_Fn>;
1550 static_assert(__expected::__is_expected<_Up>);
1551 static_assert(is_same_v<typename _Up::error_type, _Er>);
1554 return std::__invoke(std::forward<_Fn>(__f));
1556 return _Up(unexpect, std::move(error()));
1559 template<typename _Fn> requires is_move_constructible_v<_Er>
1561 and_then(_Fn&& __f) const &&
1563 using _Up = __expected::__result0<_Fn>;
1564 static_assert(__expected::__is_expected<_Up>);
1565 static_assert(is_same_v<typename _Up::error_type, _Er>);
1568 return std::__invoke(std::forward<_Fn>(__f));
1570 return _Up(unexpect, std::move(error()));
1573 template<typename _Fn>
1575 or_else(_Fn&& __f) &
1577 using _Gr = __expected::__result<_Fn, _Er&>;
1578 static_assert(__expected::__is_expected<_Gr>);
1579 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1584 return std::__invoke(std::forward<_Fn>(__f), error());
1587 template<typename _Fn>
1589 or_else(_Fn&& __f) const &
1591 using _Gr = __expected::__result<_Fn, const _Er&>;
1592 static_assert(__expected::__is_expected<_Gr>);
1593 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1598 return std::__invoke(std::forward<_Fn>(__f), error());
1601 template<typename _Fn>
1603 or_else(_Fn&& __f) &&
1605 using _Gr = __expected::__result<_Fn, _Er&&>;
1606 static_assert(__expected::__is_expected<_Gr>);
1607 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1612 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
1615 template<typename _Fn>
1617 or_else(_Fn&& __f) const &&
1619 using _Gr = __expected::__result<_Fn, const _Er&&>;
1620 static_assert(__expected::__is_expected<_Gr>);
1621 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1626 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
1629 template<typename _Fn> requires is_copy_constructible_v<_Er>
1631 transform(_Fn&& __f) &
1633 using _Up = __expected::__result0<_Fn>;
1634 using _Res = expected<_Up, _Er>;
1637 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1639 return _Res(unexpect, error());
1642 template<typename _Fn> requires is_copy_constructible_v<_Er>
1644 transform(_Fn&& __f) const &
1646 using _Up = __expected::__result0<_Fn>;
1647 using _Res = expected<_Up, _Er>;
1650 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1652 return _Res(unexpect, error());
1655 template<typename _Fn> requires is_move_constructible_v<_Er>
1657 transform(_Fn&& __f) &&
1659 using _Up = __expected::__result0<_Fn>;
1660 using _Res = expected<_Up, _Er>;
1663 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1665 return _Res(unexpect, std::move(error()));
1668 template<typename _Fn> requires is_move_constructible_v<_Er>
1670 transform(_Fn&& __f) const &&
1672 using _Up = __expected::__result0<_Fn>;
1673 using _Res = expected<_Up, _Er>;
1676 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1678 return _Res(unexpect, std::move(error()));
1681 template<typename _Fn>
1683 transform_error(_Fn&& __f) &
1685 using _Gr = __expected::__result<_Fn, _Er&>;
1686 using _Res = expected<_Tp, _Gr>;
1691 return _Res(__unexpect_inv{}, [&]() {
1692 return std::__invoke(std::forward<_Fn>(__f),
1697 template<typename _Fn>
1699 transform_error(_Fn&& __f) const &
1701 using _Gr = __expected::__result<_Fn, const _Er&>;
1702 using _Res = expected<_Tp, _Gr>;
1707 return _Res(__unexpect_inv{}, [&]() {
1708 return std::__invoke(std::forward<_Fn>(__f),
1713 template<typename _Fn>
1715 transform_error(_Fn&& __f) &&
1717 using _Gr = __expected::__result<_Fn, _Er&&>;
1718 using _Res = expected<_Tp, _Gr>;
1723 return _Res(__unexpect_inv{}, [&]() {
1724 return std::__invoke(std::forward<_Fn>(__f),
1725 std::move(_M_unex));
1729 template<typename _Fn>
1731 transform_error(_Fn&& __f) const &&
1733 using _Gr = __expected::__result<_Fn, const _Er&&>;
1734 using _Res = expected<_Tp, _Gr>;
1739 return _Res(__unexpect_inv{}, [&]() {
1740 return std::__invoke(std::forward<_Fn>(__f),
1741 std::move(_M_unex));
1745 // equality operators
1747 template<typename _Up, typename _Er2>
1748 requires is_void_v<_Up>
1749 friend constexpr bool
1750 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1751 // FIXME: noexcept(noexcept(bool(__x.error() == __y.error())))
1753 if (__x.has_value())
1754 return __y.has_value();
1756 return !__y.has_value() && bool(__x.error() == __y.error());
1759 template<typename _Er2>
1760 friend constexpr bool
1761 operator==(const expected& __x, const unexpected<_Er2>& __e)
1762 // FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
1763 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1765 friend constexpr void
1766 swap(expected& __x, expected& __y)
1767 noexcept(noexcept(__x.swap(__y)))
1768 requires requires { __x.swap(__y); }
1772 template<typename, typename> friend class expected;
1774 template<typename _Vp>
1776 _M_assign_unex(_Vp&& __v)
1780 std::construct_at(__builtin_addressof(_M_unex),
1781 std::forward<_Vp>(__v));
1782 _M_has_value = false;
1785 _M_unex = std::forward<_Vp>(__v);
1788 using __in_place_inv = __expected::__in_place_inv;
1789 using __unexpect_inv = __expected::__unexpect_inv;
1791 template<typename _Fn>
1793 expected(__in_place_inv, _Fn&& __fn)
1794 : _M_void(), _M_has_value(true)
1795 { std::forward<_Fn>(__fn)(); }
1797 template<typename _Fn>
1799 expected(__unexpect_inv, _Fn&& __fn)
1800 : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
1812_GLIBCXX_END_NAMESPACE_VERSION
1816#endif // _GLIBCXX_EXPECTED