1bdd1243dSDimitry Andric // -*- C++ -*- 2bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 3bdd1243dSDimitry Andric // 4bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7bdd1243dSDimitry Andric // 8bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric #ifndef _LIBCPP___EXPECTED_EXPECTED_H 10bdd1243dSDimitry Andric #define _LIBCPP___EXPECTED_EXPECTED_H 11bdd1243dSDimitry Andric 12bdd1243dSDimitry Andric #include <__assert> 13bdd1243dSDimitry Andric #include <__config> 14bdd1243dSDimitry Andric #include <__expected/bad_expected_access.h> 15bdd1243dSDimitry Andric #include <__expected/unexpect.h> 16bdd1243dSDimitry Andric #include <__expected/unexpected.h> 1706c3fb27SDimitry Andric #include <__functional/invoke.h> 18bdd1243dSDimitry Andric #include <__memory/addressof.h> 19bdd1243dSDimitry Andric #include <__memory/construct_at.h> 20bdd1243dSDimitry Andric #include <__type_traits/conjunction.h> 21bdd1243dSDimitry Andric #include <__type_traits/disjunction.h> 2206c3fb27SDimitry Andric #include <__type_traits/integral_constant.h> 23bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h> 24bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h> 25bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h> 26bdd1243dSDimitry Andric #include <__type_traits/is_function.h> 27*0fca6ea1SDimitry Andric #include <__type_traits/is_nothrow_assignable.h> 28bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 29bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 30bdd1243dSDimitry Andric #include <__type_traits/is_same.h> 31bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h> 32*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_constructible.h> 33bdd1243dSDimitry Andric #include <__type_traits/is_trivially_destructible.h> 34*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_relocatable.h> 35bdd1243dSDimitry Andric #include <__type_traits/is_void.h> 36bdd1243dSDimitry Andric #include <__type_traits/lazy.h> 37bdd1243dSDimitry Andric #include <__type_traits/negation.h> 38bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h> 39bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h> 4006c3fb27SDimitry Andric #include <__utility/as_const.h> 41bdd1243dSDimitry Andric #include <__utility/exception_guard.h> 42bdd1243dSDimitry Andric #include <__utility/forward.h> 43bdd1243dSDimitry Andric #include <__utility/in_place.h> 44bdd1243dSDimitry Andric #include <__utility/move.h> 45bdd1243dSDimitry Andric #include <__utility/swap.h> 4606c3fb27SDimitry Andric #include <__verbose_abort> 47bdd1243dSDimitry Andric #include <initializer_list> 48bdd1243dSDimitry Andric 49bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 50bdd1243dSDimitry Andric # pragma GCC system_header 51bdd1243dSDimitry Andric #endif 52bdd1243dSDimitry Andric 5306c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 5406c3fb27SDimitry Andric #include <__undef_macros> 5506c3fb27SDimitry Andric 56bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 23 57bdd1243dSDimitry Andric 58bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 59bdd1243dSDimitry Andric 6006c3fb27SDimitry Andric template <class _Tp, class _Err> 6106c3fb27SDimitry Andric class expected; 6206c3fb27SDimitry Andric 6306c3fb27SDimitry Andric template <class _Tp> 6406c3fb27SDimitry Andric struct __is_std_expected : false_type {}; 6506c3fb27SDimitry Andric 6606c3fb27SDimitry Andric template <class _Tp, class _Err> 6706c3fb27SDimitry Andric struct __is_std_expected<expected<_Tp, _Err>> : true_type {}; 6806c3fb27SDimitry Andric 6906c3fb27SDimitry Andric struct __expected_construct_in_place_from_invoke_tag {}; 7006c3fb27SDimitry Andric struct __expected_construct_unexpected_from_invoke_tag {}; 71bdd1243dSDimitry Andric 72bdd1243dSDimitry Andric template <class _Err, class _Arg> 73bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) { 7406c3fb27SDimitry Andric # ifndef _LIBCPP_HAS_NO_EXCEPTIONS 75bdd1243dSDimitry Andric throw bad_expected_access<_Err>(std::forward<_Arg>(__arg)); 76bdd1243dSDimitry Andric # else 77bdd1243dSDimitry Andric (void)__arg; 7806c3fb27SDimitry Andric _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode"); 79bdd1243dSDimitry Andric # endif 80bdd1243dSDimitry Andric } 81bdd1243dSDimitry Andric 827a6dacacSDimitry Andric // If parameter type `_Tp` of `__conditional_no_unique_address` is neither 837a6dacacSDimitry Andric // copyable nor movable, a constructor with this tag is provided. For that 847a6dacacSDimitry Andric // constructor, the user has to provide a function and arguments. The function 857a6dacacSDimitry Andric // must return an object of type `_Tp`. When the function is invoked by the 867a6dacacSDimitry Andric // constructor, guaranteed copy elision kicks in and the `_Tp` is constructed 877a6dacacSDimitry Andric // in place. 887a6dacacSDimitry Andric struct __conditional_no_unique_address_invoke_tag {}; 897a6dacacSDimitry Andric 907a6dacacSDimitry Andric // This class implements an object with `[[no_unique_address]]` conditionally applied to it, 917a6dacacSDimitry Andric // based on the value of `_NoUnique`. 927a6dacacSDimitry Andric // 937a6dacacSDimitry Andric // A member of this class must always have `[[no_unique_address]]` applied to 947a6dacacSDimitry Andric // it. Otherwise, the `[[no_unique_address]]` in the "`_NoUnique == true`" case 957a6dacacSDimitry Andric // would not have any effect. In the `false` case, the `__v` is not 967a6dacacSDimitry Andric // `[[no_unique_address]]`, so nullifies the effects of the "outer" 977a6dacacSDimitry Andric // `[[no_unique_address]]` regarding data layout. 987a6dacacSDimitry Andric // 997a6dacacSDimitry Andric // If we had a language feature, this class would basically be replaced by `[[no_unique_address(condition)]]`. 1007a6dacacSDimitry Andric template <bool _NoUnique, class _Tp> 1017a6dacacSDimitry Andric struct __conditional_no_unique_address; 1027a6dacacSDimitry Andric 1037a6dacacSDimitry Andric template <class _Tp> 1047a6dacacSDimitry Andric struct __conditional_no_unique_address<true, _Tp> { 1057a6dacacSDimitry Andric template <class... _Args> 1067a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(in_place_t, _Args&&... __args) 1077a6dacacSDimitry Andric : __v(std::forward<_Args>(__args)...) {} 1087a6dacacSDimitry Andric 1097a6dacacSDimitry Andric template <class _Func, class... _Args> 1107a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address( 1117a6dacacSDimitry Andric __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args) 1127a6dacacSDimitry Andric : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 1137a6dacacSDimitry Andric 1147a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v; 1157a6dacacSDimitry Andric }; 1167a6dacacSDimitry Andric 1177a6dacacSDimitry Andric template <class _Tp> 1187a6dacacSDimitry Andric struct __conditional_no_unique_address<false, _Tp> { 1197a6dacacSDimitry Andric template <class... _Args> 1207a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(in_place_t, _Args&&... __args) 1217a6dacacSDimitry Andric : __v(std::forward<_Args>(__args)...) {} 1227a6dacacSDimitry Andric 1237a6dacacSDimitry Andric template <class _Func, class... _Args> 1247a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address( 1257a6dacacSDimitry Andric __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args) 1267a6dacacSDimitry Andric : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 1277a6dacacSDimitry Andric 1287a6dacacSDimitry Andric _Tp __v; 1297a6dacacSDimitry Andric }; 1307a6dacacSDimitry Andric 1317a6dacacSDimitry Andric // This function returns whether the type `_Second` can be stuffed into the tail padding 1327a6dacacSDimitry Andric // of the `_First` type if both of them are given `[[no_unique_address]]`. 1337a6dacacSDimitry Andric template <class _First, class _Second> 1347a6dacacSDimitry Andric inline constexpr bool __fits_in_tail_padding = []() { 1357a6dacacSDimitry Andric struct __x { 1367a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _First __first; 1377a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Second __second; 1387a6dacacSDimitry Andric }; 1397a6dacacSDimitry Andric return sizeof(__x) == sizeof(_First); 1407a6dacacSDimitry Andric }(); 1417a6dacacSDimitry Andric 1427a6dacacSDimitry Andric // This class implements the storage used by `std::expected`. We have a few 1437a6dacacSDimitry Andric // goals for this storage: 1447a6dacacSDimitry Andric // 1. Whenever the underlying {_Tp | _Unex} combination has free bytes in its 1457a6dacacSDimitry Andric // tail padding, we should reuse it to store the bool discriminator of the 1467a6dacacSDimitry Andric // expected, so as to save space. 1477a6dacacSDimitry Andric // 2. Whenever the `expected<_Tp, _Unex>` as a whole has free bytes in its tail 1487a6dacacSDimitry Andric // padding, we should allow an object following the expected to be stored in 1497a6dacacSDimitry Andric // its tail padding. 1507a6dacacSDimitry Andric // 3. However, we never want a user object (say `X`) that would follow an 1517a6dacacSDimitry Andric // `expected<_Tp, _Unex>` to be stored in the padding bytes of the 1527a6dacacSDimitry Andric // underlying {_Tp | _Unex} union, if any. That is because we use 1537a6dacacSDimitry Andric // `construct_at` on that union, which would end up overwriting the `X` 1547a6dacacSDimitry Andric // member if it is stored in the tail padding of the union. 1557a6dacacSDimitry Andric // 1567a6dacacSDimitry Andric // To achieve this, `__expected_base`'s logic is implemented in an inner 1577a6dacacSDimitry Andric // `__repr` class. `__expected_base` holds one `__repr` member which is 1587a6dacacSDimitry Andric // conditionally `[[no_unique_address]]`. The `__repr` class holds the 1597a6dacacSDimitry Andric // underlying {_Tp | _Unex} union and a boolean "has value" flag. 1607a6dacacSDimitry Andric // 1617a6dacacSDimitry Andric // Which one of the `__repr_`/`__union_` members is `[[no_unique_address]]` 1627a6dacacSDimitry Andric // depends on whether the "has value" boolean fits into the tail padding of 1637a6dacacSDimitry Andric // the underlying {_Tp | _Unex} union: 1647a6dacacSDimitry Andric // 1657a6dacacSDimitry Andric // - In case the "has value" bool fits into the tail padding of the union, the 1667a6dacacSDimitry Andric // whole `__repr_` member is _not_ `[[no_unique_address]]` as it needs to be 1677a6dacacSDimitry Andric // transparently replaced on `emplace()`/`swap()` etc. 1687a6dacacSDimitry Andric // - In case the "has value" bool does not fit into the tail padding of the 1697a6dacacSDimitry Andric // union, only the union member must be transparently replaced (therefore is 1707a6dacacSDimitry Andric // _not_ `[[no_unique_address]]`) and the "has value" flag must be adjusted 1717a6dacacSDimitry Andric // manually. 1727a6dacacSDimitry Andric // 1737a6dacacSDimitry Andric // This way, the member that is transparently replaced on mutating operations 1747a6dacacSDimitry Andric // is never `[[no_unique_address]]`, satisfying the requirements from 1757a6dacacSDimitry Andric // "[basic.life]" in the standard. 1767a6dacacSDimitry Andric // 1777a6dacacSDimitry Andric // Stripped away of all superfluous elements, the layout of `__expected_base` 1787a6dacacSDimitry Andric // then looks like this: 1797a6dacacSDimitry Andric // 1807a6dacacSDimitry Andric // template <class Tp, class Err> 1817a6dacacSDimitry Andric // class expected_base { 1827a6dacacSDimitry Andric // union union_t { 1837a6dacacSDimitry Andric // [[no_unique_address]] Tp val; 1847a6dacacSDimitry Andric // [[no_unique_address]] Err unex; 1857a6dacacSDimitry Andric // }; 1867a6dacacSDimitry Andric // 1877a6dacacSDimitry Andric // static constexpr bool put_flag_in_tail = fits_in_tail_padding<union_t, bool>; 1887a6dacacSDimitry Andric // static constexpr bool allow_reusing_expected_tail_padding = !put_flag_in_tail; 1897a6dacacSDimitry Andric // 1907a6dacacSDimitry Andric // struct repr { 1917a6dacacSDimitry Andric // private: 1927a6dacacSDimitry Andric // // If "has value" fits into the tail, this should be 1937a6dacacSDimitry Andric // // `[[no_unique_address]]`, otherwise not. 1947a6dacacSDimitry Andric // [[no_unique_address]] conditional_no_unique_address< 1957a6dacacSDimitry Andric // put_flag_in_tail, 1967a6dacacSDimitry Andric // union_t>::type union_; 1977a6dacacSDimitry Andric // [[no_unique_address]] bool has_val_; 1987a6dacacSDimitry Andric // }; 1997a6dacacSDimitry Andric // 2007a6dacacSDimitry Andric // protected: 2017a6dacacSDimitry Andric // // If "has value" fits into the tail, this must _not_ be 2027a6dacacSDimitry Andric // // `[[no_unique_address]]` so that we fill out the 2037a6dacacSDimitry Andric // // complete `expected` object. 2047a6dacacSDimitry Andric // [[no_unique_address]] conditional_no_unique_address< 2057a6dacacSDimitry Andric // allow_reusing_expected_tail_padding, 2067a6dacacSDimitry Andric // repr>::type repr_; 2077a6dacacSDimitry Andric // }; 2087a6dacacSDimitry Andric // 209bdd1243dSDimitry Andric template <class _Tp, class _Err> 2107a6dacacSDimitry Andric class __expected_base { 2117a6dacacSDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 2127a6dacacSDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 2137a6dacacSDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 2147a6dacacSDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 2157a6dacacSDimitry Andric union __union_t { 2167a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = delete; 2177a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) 2187a6dacacSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 2197a6dacacSDimitry Andric is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>) 2207a6dacacSDimitry Andric = default; 2217a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = delete; 2227a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) 2237a6dacacSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 2247a6dacacSDimitry Andric is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) 2257a6dacacSDimitry Andric = default; 2267a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete; 2277a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(__union_t&&) = delete; 2287a6dacacSDimitry Andric 2297a6dacacSDimitry Andric template <class... _Args> 2307a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args) 2317a6dacacSDimitry Andric : __val_(std::forward<_Args>(__args)...) {} 2327a6dacacSDimitry Andric 2337a6dacacSDimitry Andric template <class... _Args> 2347a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args) 2357a6dacacSDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 2367a6dacacSDimitry Andric 2377a6dacacSDimitry Andric template <class _Func, class... _Args> 2387a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 2397a6dacacSDimitry Andric std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args) 2407a6dacacSDimitry Andric : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 2417a6dacacSDimitry Andric 2427a6dacacSDimitry Andric template <class _Func, class... _Args> 2437a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 2447a6dacacSDimitry Andric std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 2457a6dacacSDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 2467a6dacacSDimitry Andric 2477a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 2487a6dacacSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 2497a6dacacSDimitry Andric = default; 2507a6dacacSDimitry Andric 2517a6dacacSDimitry Andric // __repr's destructor handles this 2527a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {} 2537a6dacacSDimitry Andric 2547a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_; 2557a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; 2567a6dacacSDimitry Andric }; 2577a6dacacSDimitry Andric 2587a6dacacSDimitry Andric static constexpr bool __put_flag_in_tail = __fits_in_tail_padding<__union_t, bool>; 2597a6dacacSDimitry Andric static constexpr bool __allow_reusing_expected_tail_padding = !__put_flag_in_tail; 2607a6dacacSDimitry Andric 2617a6dacacSDimitry Andric struct __repr { 2627a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete; 2637a6dacacSDimitry Andric 2647a6dacacSDimitry Andric template <class... _Args> 2657a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag, _Args&&... __args) 2667a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(true) {} 2677a6dacacSDimitry Andric 2687a6dacacSDimitry Andric template <class... _Args> 2697a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args) 2707a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(false) {} 2717a6dacacSDimitry Andric 2727a6dacacSDimitry Andric template <class... _Args> 2737a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(std::__expected_construct_in_place_from_invoke_tag __tag, 2747a6dacacSDimitry Andric _Args&&... __args) 2757a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(true) {} 2767a6dacacSDimitry Andric 2777a6dacacSDimitry Andric template <class... _Args> 2787a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(std::__expected_construct_unexpected_from_invoke_tag __tag, 2797a6dacacSDimitry Andric _Args&&... __args) 2807a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(false) {} 2817a6dacacSDimitry Andric 2827a6dacacSDimitry Andric // The return value of `__make_union` must be constructed in place in the 2837a6dacacSDimitry Andric // `__v` member of `__union_`, relying on guaranteed copy elision. To do 2847a6dacacSDimitry Andric // this, the `__conditional_no_unique_address_invoke_tag` constructor is 2857a6dacacSDimitry Andric // called with a lambda that is immediately called inside 2867a6dacacSDimitry Andric // `__conditional_no_unique_address`'s constructor. 2877a6dacacSDimitry Andric template <class _OtherUnion> 2887a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other) 2897a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 2907a6dacacSDimitry Andric : __union_(__conditional_no_unique_address_invoke_tag{}, 2917a6dacacSDimitry Andric [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }), 2927a6dacacSDimitry Andric __has_val_(__has_val) {} 2937a6dacacSDimitry Andric 2947a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete; 2957a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) 2967a6dacacSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 2977a6dacacSDimitry Andric is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>) 2987a6dacacSDimitry Andric = default; 2997a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete; 3007a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) 3017a6dacacSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 3027a6dacacSDimitry Andric is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>) 3037a6dacacSDimitry Andric = default; 3047a6dacacSDimitry Andric 3057a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete; 3067a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(__repr&&) = delete; 3077a6dacacSDimitry Andric 3087a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__repr() 3097a6dacacSDimitry Andric requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>) 3107a6dacacSDimitry Andric = default; 3117a6dacacSDimitry Andric 3127a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__repr() 3137a6dacacSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 3147a6dacacSDimitry Andric { 3157a6dacacSDimitry Andric __destroy_union_member(); 3167a6dacacSDimitry Andric } 3177a6dacacSDimitry Andric 3187a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union() 3197a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding && 3207a6dacacSDimitry Andric (is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)) 3217a6dacacSDimitry Andric { 3227a6dacacSDimitry Andric // Note: Since the destructor of the union is trivial, this does nothing 3237a6dacacSDimitry Andric // except to end the lifetime of the union. 3247a6dacacSDimitry Andric std::destroy_at(&__union_.__v); 3257a6dacacSDimitry Andric } 3267a6dacacSDimitry Andric 3277a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union() 3287a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding && 3297a6dacacSDimitry Andric (!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)) 3307a6dacacSDimitry Andric { 3317a6dacacSDimitry Andric __destroy_union_member(); 3327a6dacacSDimitry Andric std::destroy_at(&__union_.__v); 3337a6dacacSDimitry Andric } 3347a6dacacSDimitry Andric 3357a6dacacSDimitry Andric template <class... _Args> 3367a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t, _Args&&... __args) 3377a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 3387a6dacacSDimitry Andric { 3397a6dacacSDimitry Andric std::construct_at(&__union_.__v, in_place, std::forward<_Args>(__args)...); 3407a6dacacSDimitry Andric __has_val_ = true; 3417a6dacacSDimitry Andric } 3427a6dacacSDimitry Andric 3437a6dacacSDimitry Andric template <class... _Args> 3447a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args) 3457a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 3467a6dacacSDimitry Andric { 3477a6dacacSDimitry Andric std::construct_at(&__union_.__v, unexpect, std::forward<_Args>(__args)...); 3487a6dacacSDimitry Andric __has_val_ = false; 3497a6dacacSDimitry Andric } 3507a6dacacSDimitry Andric 3517a6dacacSDimitry Andric private: 3527a6dacacSDimitry Andric template <class, class> 3537a6dacacSDimitry Andric friend class __expected_base; 3547a6dacacSDimitry Andric 3557a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member() 3567a6dacacSDimitry Andric requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>) 3577a6dacacSDimitry Andric { 3587a6dacacSDimitry Andric if (__has_val_) { 3597a6dacacSDimitry Andric std::destroy_at(std::addressof(__union_.__v.__val_)); 3607a6dacacSDimitry Andric } else { 3617a6dacacSDimitry Andric std::destroy_at(std::addressof(__union_.__v.__unex_)); 3627a6dacacSDimitry Andric } 3637a6dacacSDimitry Andric } 3647a6dacacSDimitry Andric 3657a6dacacSDimitry Andric template <class _OtherUnion> 3667a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr __union_t __make_union(bool __has_val, _OtherUnion&& __other) 3677a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 3687a6dacacSDimitry Andric { 3697a6dacacSDimitry Andric if (__has_val) 3707a6dacacSDimitry Andric return __union_t(in_place, std::forward<_OtherUnion>(__other).__val_); 3717a6dacacSDimitry Andric else 3727a6dacacSDimitry Andric return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_); 3737a6dacacSDimitry Andric } 3747a6dacacSDimitry Andric 3757a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__put_flag_in_tail, __union_t> __union_; 3767a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_; 3777a6dacacSDimitry Andric }; 3787a6dacacSDimitry Andric 3797a6dacacSDimitry Andric template <class _OtherUnion> 3807a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other) 3817a6dacacSDimitry Andric requires(__put_flag_in_tail) 3827a6dacacSDimitry Andric { 3837a6dacacSDimitry Andric if (__has_val) 3847a6dacacSDimitry Andric return __repr(in_place, std::forward<_OtherUnion>(__other).__val_); 3857a6dacacSDimitry Andric else 3867a6dacacSDimitry Andric return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_); 3877a6dacacSDimitry Andric } 3887a6dacacSDimitry Andric 3897a6dacacSDimitry Andric protected: 3907a6dacacSDimitry Andric template <class... _Args> 3917a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args) 3927a6dacacSDimitry Andric : __repr_(in_place, std::forward<_Args>(__args)...) {} 3937a6dacacSDimitry Andric 3947a6dacacSDimitry Andric // In case we copy/move construct from another `expected` we need to create 3957a6dacacSDimitry Andric // our `expected` so that it either has a value or not, depending on the "has 3967a6dacacSDimitry Andric // value" flag of the other `expected`. To do this without falling back on 3977a6dacacSDimitry Andric // `std::construct_at` we rely on guaranteed copy elision using two helper 3987a6dacacSDimitry Andric // functions `__make_repr` and `__make_union`. There have to be two since 3997a6dacacSDimitry Andric // there are two data layouts with different members being 4007a6dacacSDimitry Andric // `[[no_unique_address]]`. GCC (as of version 13) does not do guaranteed 4017a6dacacSDimitry Andric // copy elision when initializing `[[no_unique_address]]` members. The two 4027a6dacacSDimitry Andric // cases are: 4037a6dacacSDimitry Andric // 4047a6dacacSDimitry Andric // - `__make_repr`: This is used when the "has value" flag lives in the tail 4057a6dacacSDimitry Andric // of the union. In this case, the `__repr` member is _not_ 4067a6dacacSDimitry Andric // `[[no_unique_address]]`. 4077a6dacacSDimitry Andric // - `__make_union`: When the "has value" flag does _not_ fit in the tail of 4087a6dacacSDimitry Andric // the union, the `__repr` member is `[[no_unique_address]]` and the union 4097a6dacacSDimitry Andric // is not. 4107a6dacacSDimitry Andric // 4117a6dacacSDimitry Andric // This constructor "catches" the first case and leaves the second case to 4127a6dacacSDimitry Andric // `__union_t`, its constructors and `__make_union`. 4137a6dacacSDimitry Andric template <class _OtherUnion> 4147a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other) 4157a6dacacSDimitry Andric requires(__put_flag_in_tail) 4167a6dacacSDimitry Andric : __repr_(__conditional_no_unique_address_invoke_tag{}, 4177a6dacacSDimitry Andric [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {} 4187a6dacacSDimitry Andric 4197a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() { 4207a6dacacSDimitry Andric if constexpr (__put_flag_in_tail) 4217a6dacacSDimitry Andric std::destroy_at(&__repr_.__v); 4227a6dacacSDimitry Andric else 4237a6dacacSDimitry Andric __repr_.__v.__destroy_union(); 4247a6dacacSDimitry Andric } 4257a6dacacSDimitry Andric 4267a6dacacSDimitry Andric template <class _Tag, class... _Args> 4277a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args) { 4287a6dacacSDimitry Andric if constexpr (__put_flag_in_tail) 4297a6dacacSDimitry Andric std::construct_at(&__repr_.__v, __tag, std::forward<_Args>(__args)...); 4307a6dacacSDimitry Andric else 4317a6dacacSDimitry Andric __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...); 4327a6dacacSDimitry Andric } 4337a6dacacSDimitry Andric 4347a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; } 4357a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; } 4367a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; } 4377a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& __val() { return __repr_.__v.__union_.__v.__val_; } 4387a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& __val() const { return __repr_.__v.__union_.__v.__val_; } 4397a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_; } 4407a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; } 4417a6dacacSDimitry Andric 4427a6dacacSDimitry Andric private: 4437a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__allow_reusing_expected_tail_padding, __repr> __repr_; 4447a6dacacSDimitry Andric }; 4457a6dacacSDimitry Andric 4467a6dacacSDimitry Andric template <class _Tp, class _Err> 4477a6dacacSDimitry Andric class expected : private __expected_base<_Tp, _Err> { 448cb14a3feSDimitry Andric static_assert(!is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, in_place_t> && 449cb14a3feSDimitry Andric !is_same_v<remove_cv_t<_Tp>, unexpect_t> && !__is_std_unexpected<remove_cv_t<_Tp>>::value && 450cb14a3feSDimitry Andric __valid_std_unexpected<_Err>::value, 451bdd1243dSDimitry Andric "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a " 452bdd1243dSDimitry Andric "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a " 453bdd1243dSDimitry Andric "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the " 454bdd1243dSDimitry Andric "definition of the template expected<T, E> with a type for the E parameter that is not a valid " 455bdd1243dSDimitry Andric "template argument for unexpected is ill-formed."); 456bdd1243dSDimitry Andric 457bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 458bdd1243dSDimitry Andric friend class expected; 459bdd1243dSDimitry Andric 4607a6dacacSDimitry Andric using __base = __expected_base<_Tp, _Err>; 4617a6dacacSDimitry Andric 462bdd1243dSDimitry Andric public: 463bdd1243dSDimitry Andric using value_type = _Tp; 464bdd1243dSDimitry Andric using error_type = _Err; 465bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 466bdd1243dSDimitry Andric 467*0fca6ea1SDimitry Andric using __trivially_relocatable = 468*0fca6ea1SDimitry Andric __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value, 469*0fca6ea1SDimitry Andric expected, 470*0fca6ea1SDimitry Andric void>; 471*0fca6ea1SDimitry Andric 472bdd1243dSDimitry Andric template <class _Up> 473bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric // [expected.object.ctor], constructors 476cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened 477bdd1243dSDimitry Andric requires is_default_constructible_v<_Tp> 4787a6dacacSDimitry Andric : __base(in_place) {} 479bdd1243dSDimitry Andric 480bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 481bdd1243dSDimitry Andric 482bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 483cb14a3feSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Tp> && 484bdd1243dSDimitry Andric is_trivially_copy_constructible_v<_Err>) 485bdd1243dSDimitry Andric = default; 486bdd1243dSDimitry Andric 487cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) noexcept( 488cb14a3feSDimitry Andric is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened 489bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && 490bdd1243dSDimitry Andric !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)) 4917a6dacacSDimitry Andric : __base(__other.__has_val(), __other.__union()) {} 492bdd1243dSDimitry Andric 493bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 494cb14a3feSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Tp> && 495cb14a3feSDimitry Andric is_trivially_move_constructible_v<_Err>) 496bdd1243dSDimitry Andric = default; 497bdd1243dSDimitry Andric 498cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) noexcept( 499cb14a3feSDimitry Andric is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>) 500bdd1243dSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && 501bdd1243dSDimitry Andric !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)) 5027a6dacacSDimitry Andric : __base(__other.__has_val(), std::move(__other.__union())) {} 503bdd1243dSDimitry Andric 504bdd1243dSDimitry Andric private: 505bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual> 506bdd1243dSDimitry Andric using __can_convert = 507bdd1243dSDimitry Andric _And< is_constructible<_Tp, _UfQual>, 508bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 5095f757f3fSDimitry Andric _If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value, 510*0fca6ea1SDimitry Andric _And< 511*0fca6ea1SDimitry Andric _Not<_And<is_same<_Tp, _Up>, is_same<_Err, _OtherErr>>>, // use the copy constructor instead, see #92676 512*0fca6ea1SDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>, 513bdd1243dSDimitry Andric _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>, 514bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>, 515bdd1243dSDimitry Andric _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>, 516bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>, 517bdd1243dSDimitry Andric _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>, 518bdd1243dSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>, 5195f757f3fSDimitry Andric _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>>, 5205f757f3fSDimitry Andric true_type>, 521bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 522bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 523bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 524bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >; 525bdd1243dSDimitry Andric 52606c3fb27SDimitry Andric template <class _Func, class... _Args> 52706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 52806c3fb27SDimitry Andric std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 5297a6dacacSDimitry Andric : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {} 53006c3fb27SDimitry Andric 53106c3fb27SDimitry Andric template <class _Func, class... _Args> 53206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 53306c3fb27SDimitry Andric std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 5347a6dacacSDimitry Andric : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {} 535bdd1243dSDimitry Andric 536bdd1243dSDimitry Andric public: 537bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 538bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value 539bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> || 540bdd1243dSDimitry Andric !is_convertible_v<const _OtherErr&, _Err>) 541cb14a3feSDimitry Andric expected(const expected<_Up, _OtherErr>& __other) noexcept( 542cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, const _Up&> && 543bdd1243dSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 5447a6dacacSDimitry Andric : __base(__other.__has_val(), __other.__union()) {} 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 547bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value 548bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>) 549cb14a3feSDimitry Andric expected(expected<_Up, _OtherErr>&& __other) noexcept( 550cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 5517a6dacacSDimitry Andric : __base(__other.__has_val(), std::move(__other.__union())) {} 552bdd1243dSDimitry Andric 553bdd1243dSDimitry Andric template <class _Up = _Tp> 554bdd1243dSDimitry Andric requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> && 5555f757f3fSDimitry Andric is_constructible_v<_Tp, _Up> && !__is_std_unexpected<remove_cvref_t<_Up>>::value && 5565f757f3fSDimitry Andric (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value)) 557bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>) 558b121cb00SDimitry Andric expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened 5597a6dacacSDimitry Andric : __base(in_place, std::forward<_Up>(__u)) {} 560bdd1243dSDimitry Andric 561bdd1243dSDimitry Andric template <class _OtherErr> 562bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 563cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected( 564cb14a3feSDimitry Andric const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 5657a6dacacSDimitry Andric : __base(unexpect, __unex.error()) {} 566bdd1243dSDimitry Andric 567bdd1243dSDimitry Andric template <class _OtherErr> 568bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 569bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 570cb14a3feSDimitry Andric expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 5717a6dacacSDimitry Andric : __base(unexpect, std::move(__unex.error())) {} 572bdd1243dSDimitry Andric 573bdd1243dSDimitry Andric template <class... _Args> 574bdd1243dSDimitry Andric requires is_constructible_v<_Tp, _Args...> 575cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) noexcept( 576cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, _Args...>) // strengthened 5777a6dacacSDimitry Andric : __base(in_place, std::forward<_Args>(__args)...) {} 578bdd1243dSDimitry Andric 579bdd1243dSDimitry Andric template <class _Up, class... _Args> 580bdd1243dSDimitry Andric requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... > 581cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 582cb14a3feSDimitry Andric is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened 5837a6dacacSDimitry Andric : __base(in_place, __il, std::forward<_Args>(__args)...) {} 584bdd1243dSDimitry Andric 585bdd1243dSDimitry Andric template <class... _Args> 586bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 587cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept( 588cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, _Args...>) // strengthened 5897a6dacacSDimitry Andric : __base(unexpect, std::forward<_Args>(__args)...) {} 590bdd1243dSDimitry Andric 591bdd1243dSDimitry Andric template <class _Up, class... _Args> 592bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 593cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 594cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 5957a6dacacSDimitry Andric : __base(unexpect, __il, std::forward<_Args>(__args)...) {} 596bdd1243dSDimitry Andric 597bdd1243dSDimitry Andric // [expected.object.dtor], destructor 598bdd1243dSDimitry Andric 5997a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() = default; 600bdd1243dSDimitry Andric 601bdd1243dSDimitry Andric private: 6027a6dacacSDimitry Andric template <class _Tag, class _OtherTag, class _T1, class _T2, class... _Args> 6037a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(_T2& __oldval, _Args&&... __args) { 604bdd1243dSDimitry Andric if constexpr (is_nothrow_constructible_v<_T1, _Args...>) { 6057a6dacacSDimitry Andric this->__destroy(); 6067a6dacacSDimitry Andric this->__construct(_Tag{}, std::forward<_Args>(__args)...); 607bdd1243dSDimitry Andric } else if constexpr (is_nothrow_move_constructible_v<_T1>) { 608bdd1243dSDimitry Andric _T1 __tmp(std::forward<_Args>(__args)...); 6097a6dacacSDimitry Andric this->__destroy(); 6107a6dacacSDimitry Andric this->__construct(_Tag{}, std::move(__tmp)); 611bdd1243dSDimitry Andric } else { 612bdd1243dSDimitry Andric static_assert( 613bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_T2>, 614bdd1243dSDimitry Andric "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can " 615bdd1243dSDimitry Andric "be reverted to the previous state in case an exception is thrown during the assignment."); 616bdd1243dSDimitry Andric _T2 __tmp(std::move(__oldval)); 6177a6dacacSDimitry Andric this->__destroy(); 6187a6dacacSDimitry Andric auto __trans = std::__make_exception_guard([&] { this->__construct(_OtherTag{}, std::move(__tmp)); }); 6197a6dacacSDimitry Andric this->__construct(_Tag{}, std::forward<_Args>(__args)...); 620bdd1243dSDimitry Andric __trans.__complete(); 621bdd1243dSDimitry Andric } 622bdd1243dSDimitry Andric } 623bdd1243dSDimitry Andric 624bdd1243dSDimitry Andric public: 625bdd1243dSDimitry Andric // [expected.object.assign], assignment 626bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 627bdd1243dSDimitry Andric 628cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept( 629cb14a3feSDimitry Andric is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_assignable_v<_Err> && 630bdd1243dSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 631cb14a3feSDimitry Andric requires(is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Err> && 632bdd1243dSDimitry Andric is_copy_constructible_v<_Err> && 633cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 634bdd1243dSDimitry Andric { 6357a6dacacSDimitry Andric if (this->__has_val() && __rhs.__has_val()) { 6367a6dacacSDimitry Andric this->__val() = __rhs.__val(); 6377a6dacacSDimitry Andric } else if (this->__has_val()) { 6387a6dacacSDimitry Andric __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), __rhs.__unex()); 6397a6dacacSDimitry Andric } else if (__rhs.__has_val()) { 6407a6dacacSDimitry Andric __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), __rhs.__val()); 641bdd1243dSDimitry Andric } else { 6427a6dacacSDimitry Andric this->__unex() = __rhs.__unex(); 643bdd1243dSDimitry Andric } 644bdd1243dSDimitry Andric return *this; 645bdd1243dSDimitry Andric } 646bdd1243dSDimitry Andric 647cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& 648cb14a3feSDimitry Andric operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp> && 649cb14a3feSDimitry Andric is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) 650cb14a3feSDimitry Andric requires(is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp> && is_move_constructible_v<_Err> && 651bdd1243dSDimitry Andric is_move_assignable_v<_Err> && 652cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 653bdd1243dSDimitry Andric { 6547a6dacacSDimitry Andric if (this->__has_val() && __rhs.__has_val()) { 6557a6dacacSDimitry Andric this->__val() = std::move(__rhs.__val()); 6567a6dacacSDimitry Andric } else if (this->__has_val()) { 6577a6dacacSDimitry Andric __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), std::move(__rhs.__unex())); 6587a6dacacSDimitry Andric } else if (__rhs.__has_val()) { 6597a6dacacSDimitry Andric __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), std::move(__rhs.__val())); 660bdd1243dSDimitry Andric } else { 6617a6dacacSDimitry Andric this->__unex() = std::move(__rhs.__unex()); 662bdd1243dSDimitry Andric } 663bdd1243dSDimitry Andric return *this; 664bdd1243dSDimitry Andric } 665bdd1243dSDimitry Andric 666bdd1243dSDimitry Andric template <class _Up = _Tp> 667bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v) 668cb14a3feSDimitry Andric requires(!is_same_v<expected, remove_cvref_t<_Up>> && !__is_std_unexpected<remove_cvref_t<_Up>>::value && 669cb14a3feSDimitry Andric is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> && 670cb14a3feSDimitry Andric (is_nothrow_constructible_v<_Tp, _Up> || is_nothrow_move_constructible_v<_Tp> || 671bdd1243dSDimitry Andric is_nothrow_move_constructible_v<_Err>)) 672bdd1243dSDimitry Andric { 6737a6dacacSDimitry Andric if (this->__has_val()) { 6747a6dacacSDimitry Andric this->__val() = std::forward<_Up>(__v); 675bdd1243dSDimitry Andric } else { 6767a6dacacSDimitry Andric __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), std::forward<_Up>(__v)); 677bdd1243dSDimitry Andric } 678bdd1243dSDimitry Andric return *this; 679bdd1243dSDimitry Andric } 680bdd1243dSDimitry Andric 681bdd1243dSDimitry Andric private: 682bdd1243dSDimitry Andric template <class _OtherErrQual> 683bdd1243dSDimitry Andric static constexpr bool __can_assign_from_unexpected = 684bdd1243dSDimitry Andric _And< is_constructible<_Err, _OtherErrQual>, 685bdd1243dSDimitry Andric is_assignable<_Err&, _OtherErrQual>, 686bdd1243dSDimitry Andric _Lazy<_Or, 687bdd1243dSDimitry Andric is_nothrow_constructible<_Err, _OtherErrQual>, 688bdd1243dSDimitry Andric is_nothrow_move_constructible<_Tp>, 689bdd1243dSDimitry Andric is_nothrow_move_constructible<_Err>> >::value; 690bdd1243dSDimitry Andric 691bdd1243dSDimitry Andric public: 692bdd1243dSDimitry Andric template <class _OtherErr> 693bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<const _OtherErr&>) 694bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 6957a6dacacSDimitry Andric if (this->__has_val()) { 6967a6dacacSDimitry Andric __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), __un.error()); 697bdd1243dSDimitry Andric } else { 6987a6dacacSDimitry Andric this->__unex() = __un.error(); 699bdd1243dSDimitry Andric } 700bdd1243dSDimitry Andric return *this; 701bdd1243dSDimitry Andric } 702bdd1243dSDimitry Andric 703bdd1243dSDimitry Andric template <class _OtherErr> 704bdd1243dSDimitry Andric requires(__can_assign_from_unexpected<_OtherErr>) 705bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 7067a6dacacSDimitry Andric if (this->__has_val()) { 7077a6dacacSDimitry Andric __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), std::move(__un.error())); 708bdd1243dSDimitry Andric } else { 7097a6dacacSDimitry Andric this->__unex() = std::move(__un.error()); 710bdd1243dSDimitry Andric } 711bdd1243dSDimitry Andric return *this; 712bdd1243dSDimitry Andric } 713bdd1243dSDimitry Andric 714bdd1243dSDimitry Andric template <class... _Args> 715bdd1243dSDimitry Andric requires is_nothrow_constructible_v<_Tp, _Args...> 716bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept { 7177a6dacacSDimitry Andric this->__destroy(); 7187a6dacacSDimitry Andric this->__construct(in_place, std::forward<_Args>(__args)...); 7197a6dacacSDimitry Andric return this->__val(); 720bdd1243dSDimitry Andric } 721bdd1243dSDimitry Andric 722bdd1243dSDimitry Andric template <class _Up, class... _Args> 723bdd1243dSDimitry Andric requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...> 724bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept { 7257a6dacacSDimitry Andric this->__destroy(); 7267a6dacacSDimitry Andric this->__construct(in_place, __il, std::forward<_Args>(__args)...); 7277a6dacacSDimitry Andric return this->__val(); 728bdd1243dSDimitry Andric } 729bdd1243dSDimitry Andric 730bdd1243dSDimitry Andric public: 731bdd1243dSDimitry Andric // [expected.object.swap], swap 732cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 733cb14a3feSDimitry Andric swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp> && 734cb14a3feSDimitry Andric is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 735cb14a3feSDimitry Andric requires(is_swappable_v<_Tp> && is_swappable_v<_Err> && is_move_constructible_v<_Tp> && 736bdd1243dSDimitry Andric is_move_constructible_v<_Err> && 737cb14a3feSDimitry Andric (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>)) 738bdd1243dSDimitry Andric { 7397a6dacacSDimitry Andric auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) { 740bdd1243dSDimitry Andric if constexpr (is_nothrow_move_constructible_v<_Err>) { 7417a6dacacSDimitry Andric _Err __tmp(std::move(__with_err.__unex())); 7427a6dacacSDimitry Andric __with_err.__destroy(); 7437a6dacacSDimitry Andric auto __trans = std::__make_exception_guard([&] { __with_err.__construct(unexpect, std::move(__tmp)); }); 7447a6dacacSDimitry Andric __with_err.__construct(in_place, std::move(__with_val.__val())); 745bdd1243dSDimitry Andric __trans.__complete(); 7467a6dacacSDimitry Andric __with_val.__destroy(); 7477a6dacacSDimitry Andric __with_val.__construct(unexpect, std::move(__tmp)); 748bdd1243dSDimitry Andric } else { 749bdd1243dSDimitry Andric static_assert(is_nothrow_move_constructible_v<_Tp>, 750bdd1243dSDimitry Andric "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so " 751bdd1243dSDimitry Andric "that it can be reverted to the previous state in case an exception is thrown during swap."); 7527a6dacacSDimitry Andric _Tp __tmp(std::move(__with_val.__val())); 7537a6dacacSDimitry Andric __with_val.__destroy(); 7547a6dacacSDimitry Andric auto __trans = std::__make_exception_guard([&] { __with_val.__construct(in_place, std::move(__tmp)); }); 7557a6dacacSDimitry Andric __with_val.__construct(unexpect, std::move(__with_err.__unex())); 756bdd1243dSDimitry Andric __trans.__complete(); 7577a6dacacSDimitry Andric __with_err.__destroy(); 7587a6dacacSDimitry Andric __with_err.__construct(in_place, std::move(__tmp)); 759bdd1243dSDimitry Andric } 760bdd1243dSDimitry Andric }; 761bdd1243dSDimitry Andric 7627a6dacacSDimitry Andric if (this->__has_val()) { 7637a6dacacSDimitry Andric if (__rhs.__has_val()) { 764bdd1243dSDimitry Andric using std::swap; 7657a6dacacSDimitry Andric swap(this->__val(), __rhs.__val()); 766bdd1243dSDimitry Andric } else { 767bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 768bdd1243dSDimitry Andric } 769bdd1243dSDimitry Andric } else { 7707a6dacacSDimitry Andric if (__rhs.__has_val()) { 771bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 772bdd1243dSDimitry Andric } else { 773bdd1243dSDimitry Andric using std::swap; 7747a6dacacSDimitry Andric swap(this->__unex(), __rhs.__unex()); 775bdd1243dSDimitry Andric } 776bdd1243dSDimitry Andric } 777bdd1243dSDimitry Andric } 778bdd1243dSDimitry Andric 779cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) 780bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 781bdd1243dSDimitry Andric { 782bdd1243dSDimitry Andric __x.swap(__y); 783bdd1243dSDimitry Andric } 784bdd1243dSDimitry Andric 785bdd1243dSDimitry Andric // [expected.object.obs], observers 786bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept { 7877a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 7887a6dacacSDimitry Andric this->__has_val(), "expected::operator-> requires the expected to contain a value"); 7897a6dacacSDimitry Andric return std::addressof(this->__val()); 790bdd1243dSDimitry Andric } 791bdd1243dSDimitry Andric 792bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept { 7937a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 7947a6dacacSDimitry Andric this->__has_val(), "expected::operator-> requires the expected to contain a value"); 7957a6dacacSDimitry Andric return std::addressof(this->__val()); 796bdd1243dSDimitry Andric } 797bdd1243dSDimitry Andric 798bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { 7997a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8007a6dacacSDimitry Andric this->__has_val(), "expected::operator* requires the expected to contain a value"); 8017a6dacacSDimitry Andric return this->__val(); 802bdd1243dSDimitry Andric } 803bdd1243dSDimitry Andric 804bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { 8057a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8067a6dacacSDimitry Andric this->__has_val(), "expected::operator* requires the expected to contain a value"); 8077a6dacacSDimitry Andric return this->__val(); 808bdd1243dSDimitry Andric } 809bdd1243dSDimitry Andric 810bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { 8117a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8127a6dacacSDimitry Andric this->__has_val(), "expected::operator* requires the expected to contain a value"); 8137a6dacacSDimitry Andric return std::move(this->__val()); 814bdd1243dSDimitry Andric } 815bdd1243dSDimitry Andric 816bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { 8177a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8187a6dacacSDimitry Andric this->__has_val(), "expected::operator* requires the expected to contain a value"); 8197a6dacacSDimitry Andric return std::move(this->__val()); 820bdd1243dSDimitry Andric } 821bdd1243dSDimitry Andric 8227a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); } 823bdd1243dSDimitry Andric 8247a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } 825bdd1243dSDimitry Andric 826bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { 82706c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 8287a6dacacSDimitry Andric if (!this->__has_val()) { 82906c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 830bdd1243dSDimitry Andric } 8317a6dacacSDimitry Andric return this->__val(); 832bdd1243dSDimitry Andric } 833bdd1243dSDimitry Andric 834bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { 83506c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 8367a6dacacSDimitry Andric if (!this->__has_val()) { 83706c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::as_const(error())); 838bdd1243dSDimitry Andric } 8397a6dacacSDimitry Andric return this->__val(); 840bdd1243dSDimitry Andric } 841bdd1243dSDimitry Andric 842bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { 84306c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 84406c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 8457a6dacacSDimitry Andric if (!this->__has_val()) { 84606c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 847bdd1243dSDimitry Andric } 8487a6dacacSDimitry Andric return std::move(this->__val()); 849bdd1243dSDimitry Andric } 850bdd1243dSDimitry Andric 851bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { 85206c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, 85306c3fb27SDimitry Andric "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); 8547a6dacacSDimitry Andric if (!this->__has_val()) { 85506c3fb27SDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(error())); 856bdd1243dSDimitry Andric } 8577a6dacacSDimitry Andric return std::move(this->__val()); 858bdd1243dSDimitry Andric } 859bdd1243dSDimitry Andric 860bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 8617a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8627a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 8637a6dacacSDimitry Andric return this->__unex(); 864bdd1243dSDimitry Andric } 865bdd1243dSDimitry Andric 866bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 8677a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8687a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 8697a6dacacSDimitry Andric return this->__unex(); 870bdd1243dSDimitry Andric } 871bdd1243dSDimitry Andric 872bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 8737a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8747a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 8757a6dacacSDimitry Andric return std::move(this->__unex()); 876bdd1243dSDimitry Andric } 877bdd1243dSDimitry Andric 878bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 8797a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 8807a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 8817a6dacacSDimitry Andric return std::move(this->__unex()); 882bdd1243dSDimitry Andric } 883bdd1243dSDimitry Andric 884bdd1243dSDimitry Andric template <class _Up> 885bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { 886bdd1243dSDimitry Andric static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); 887bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 8887a6dacacSDimitry Andric return this->__has_val() ? this->__val() : static_cast<_Tp>(std::forward<_Up>(__v)); 889bdd1243dSDimitry Andric } 890bdd1243dSDimitry Andric 891bdd1243dSDimitry Andric template <class _Up> 892bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { 893bdd1243dSDimitry Andric static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); 894bdd1243dSDimitry Andric static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); 8957a6dacacSDimitry Andric return this->__has_val() ? std::move(this->__val()) : static_cast<_Tp>(std::forward<_Up>(__v)); 896bdd1243dSDimitry Andric } 897bdd1243dSDimitry Andric 89806c3fb27SDimitry Andric template <class _Up = _Err> 89906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 90006c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 90106c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 90206c3fb27SDimitry Andric if (has_value()) 90306c3fb27SDimitry Andric return std::forward<_Up>(__error); 90406c3fb27SDimitry Andric return error(); 90506c3fb27SDimitry Andric } 90606c3fb27SDimitry Andric 90706c3fb27SDimitry Andric template <class _Up = _Err> 90806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 90906c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 91006c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 91106c3fb27SDimitry Andric if (has_value()) 91206c3fb27SDimitry Andric return std::forward<_Up>(__error); 91306c3fb27SDimitry Andric return std::move(error()); 91406c3fb27SDimitry Andric } 91506c3fb27SDimitry Andric 91606c3fb27SDimitry Andric // [expected.void.monadic], monadic 91706c3fb27SDimitry Andric template <class _Func> 91806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 91906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 92006c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>; 9215f757f3fSDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected"); 92206c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 9235f757f3fSDimitry Andric "The result of f(**this) must have the same error_type as this expected"); 92406c3fb27SDimitry Andric if (has_value()) { 9257a6dacacSDimitry Andric return std::invoke(std::forward<_Func>(__f), this->__val()); 92606c3fb27SDimitry Andric } 92706c3fb27SDimitry Andric return _Up(unexpect, error()); 92806c3fb27SDimitry Andric } 92906c3fb27SDimitry Andric 93006c3fb27SDimitry Andric template <class _Func> 93106c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 93206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 93306c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>; 9345f757f3fSDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected"); 93506c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 9365f757f3fSDimitry Andric "The result of f(**this) must have the same error_type as this expected"); 93706c3fb27SDimitry Andric if (has_value()) { 9387a6dacacSDimitry Andric return std::invoke(std::forward<_Func>(__f), this->__val()); 93906c3fb27SDimitry Andric } 94006c3fb27SDimitry Andric return _Up(unexpect, error()); 94106c3fb27SDimitry Andric } 94206c3fb27SDimitry Andric 94306c3fb27SDimitry Andric template <class _Func> 94406c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 94506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 94606c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>; 94706c3fb27SDimitry Andric static_assert( 9485f757f3fSDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected"); 94906c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 9505f757f3fSDimitry Andric "The result of f(std::move(**this)) must have the same error_type as this expected"); 95106c3fb27SDimitry Andric if (has_value()) { 9527a6dacacSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(this->__val())); 95306c3fb27SDimitry Andric } 95406c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 95506c3fb27SDimitry Andric } 95606c3fb27SDimitry Andric 95706c3fb27SDimitry Andric template <class _Func> 95806c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 95906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 96006c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>; 96106c3fb27SDimitry Andric static_assert( 9625f757f3fSDimitry Andric __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected"); 96306c3fb27SDimitry Andric static_assert(is_same_v<typename _Up::error_type, _Err>, 9645f757f3fSDimitry Andric "The result of f(std::move(**this)) must have the same error_type as this expected"); 96506c3fb27SDimitry Andric if (has_value()) { 9667a6dacacSDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(this->__val())); 96706c3fb27SDimitry Andric } 96806c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 96906c3fb27SDimitry Andric } 97006c3fb27SDimitry Andric 97106c3fb27SDimitry Andric template <class _Func> 97206c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 97306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 97406c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 97506c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 97606c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 97706c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 97806c3fb27SDimitry Andric if (has_value()) { 9797a6dacacSDimitry Andric return _Gp(in_place, this->__val()); 98006c3fb27SDimitry Andric } 98106c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 98206c3fb27SDimitry Andric } 98306c3fb27SDimitry Andric 98406c3fb27SDimitry Andric template <class _Func> 98506c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 98606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 98706c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 98806c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 98906c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 99006c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 99106c3fb27SDimitry Andric if (has_value()) { 9927a6dacacSDimitry Andric return _Gp(in_place, this->__val()); 99306c3fb27SDimitry Andric } 99406c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 99506c3fb27SDimitry Andric } 99606c3fb27SDimitry Andric 99706c3fb27SDimitry Andric template <class _Func> 99806c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 99906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 100006c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 100106c3fb27SDimitry Andric static_assert( 100206c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 100306c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 100406c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 100506c3fb27SDimitry Andric if (has_value()) { 10067a6dacacSDimitry Andric return _Gp(in_place, std::move(this->__val())); 100706c3fb27SDimitry Andric } 100806c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 100906c3fb27SDimitry Andric } 101006c3fb27SDimitry Andric 101106c3fb27SDimitry Andric template <class _Func> 101206c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 101306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 101406c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 101506c3fb27SDimitry Andric static_assert( 101606c3fb27SDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 101706c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 101806c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 101906c3fb27SDimitry Andric if (has_value()) { 10207a6dacacSDimitry Andric return _Gp(in_place, std::move(this->__val())); 102106c3fb27SDimitry Andric } 102206c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 102306c3fb27SDimitry Andric } 102406c3fb27SDimitry Andric 102506c3fb27SDimitry Andric template <class _Func> 102606c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 102706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 102806c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>; 102906c3fb27SDimitry Andric if (!has_value()) { 103006c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 103106c3fb27SDimitry Andric } 103206c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 1033cb14a3feSDimitry Andric return expected<_Up, _Err>( 10347a6dacacSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__val()); 103506c3fb27SDimitry Andric } else { 10367a6dacacSDimitry Andric std::invoke(std::forward<_Func>(__f), this->__val()); 103706c3fb27SDimitry Andric return expected<_Up, _Err>(); 103806c3fb27SDimitry Andric } 103906c3fb27SDimitry Andric } 104006c3fb27SDimitry Andric 104106c3fb27SDimitry Andric template <class _Func> 104206c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 104306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 104406c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>; 104506c3fb27SDimitry Andric if (!has_value()) { 104606c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 104706c3fb27SDimitry Andric } 104806c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 1049cb14a3feSDimitry Andric return expected<_Up, _Err>( 10507a6dacacSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__val()); 105106c3fb27SDimitry Andric } else { 10527a6dacacSDimitry Andric std::invoke(std::forward<_Func>(__f), this->__val()); 105306c3fb27SDimitry Andric return expected<_Up, _Err>(); 105406c3fb27SDimitry Andric } 105506c3fb27SDimitry Andric } 105606c3fb27SDimitry Andric 105706c3fb27SDimitry Andric template <class _Func> 105806c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 105906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 106006c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>; 106106c3fb27SDimitry Andric if (!has_value()) { 106206c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 106306c3fb27SDimitry Andric } 106406c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 106506c3fb27SDimitry Andric return expected<_Up, _Err>( 10667a6dacacSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__val())); 106706c3fb27SDimitry Andric } else { 10687a6dacacSDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(this->__val())); 106906c3fb27SDimitry Andric return expected<_Up, _Err>(); 107006c3fb27SDimitry Andric } 107106c3fb27SDimitry Andric } 107206c3fb27SDimitry Andric 107306c3fb27SDimitry Andric template <class _Func> 107406c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 107506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 107606c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>; 107706c3fb27SDimitry Andric if (!has_value()) { 107806c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 107906c3fb27SDimitry Andric } 108006c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 108106c3fb27SDimitry Andric return expected<_Up, _Err>( 10827a6dacacSDimitry Andric __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__val())); 108306c3fb27SDimitry Andric } else { 10847a6dacacSDimitry Andric std::invoke(std::forward<_Func>(__f), std::move(this->__val())); 108506c3fb27SDimitry Andric return expected<_Up, _Err>(); 108606c3fb27SDimitry Andric } 108706c3fb27SDimitry Andric } 108806c3fb27SDimitry Andric 108906c3fb27SDimitry Andric template <class _Func> 109006c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&> 109106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 109206c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 109306c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 109406c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 109506c3fb27SDimitry Andric if (has_value()) { 10967a6dacacSDimitry Andric return expected<_Tp, _Gp>(in_place, this->__val()); 109706c3fb27SDimitry Andric } 109806c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 109906c3fb27SDimitry Andric } 110006c3fb27SDimitry Andric 110106c3fb27SDimitry Andric template <class _Func> 110206c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&> 110306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 110406c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 110506c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 110606c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 110706c3fb27SDimitry Andric if (has_value()) { 11087a6dacacSDimitry Andric return expected<_Tp, _Gp>(in_place, this->__val()); 110906c3fb27SDimitry Andric } 111006c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 111106c3fb27SDimitry Andric } 111206c3fb27SDimitry Andric 111306c3fb27SDimitry Andric template <class _Func> 111406c3fb27SDimitry Andric requires is_constructible_v<_Tp, _Tp&&> 111506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 111606c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 111706c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 111806c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 111906c3fb27SDimitry Andric if (has_value()) { 11207a6dacacSDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(this->__val())); 112106c3fb27SDimitry Andric } 112206c3fb27SDimitry Andric return expected<_Tp, _Gp>( 112306c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 112406c3fb27SDimitry Andric } 112506c3fb27SDimitry Andric 112606c3fb27SDimitry Andric template <class _Func> 112706c3fb27SDimitry Andric requires is_constructible_v<_Tp, const _Tp&&> 112806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 112906c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 113006c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 113106c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 113206c3fb27SDimitry Andric if (has_value()) { 11337a6dacacSDimitry Andric return expected<_Tp, _Gp>(in_place, std::move(this->__val())); 113406c3fb27SDimitry Andric } 113506c3fb27SDimitry Andric return expected<_Tp, _Gp>( 113606c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 113706c3fb27SDimitry Andric } 113806c3fb27SDimitry Andric 1139bdd1243dSDimitry Andric // [expected.object.eq], equality operators 1140bdd1243dSDimitry Andric template <class _T2, class _E2> 1141bdd1243dSDimitry Andric requires(!is_void_v<_T2>) 1142bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 11437a6dacacSDimitry Andric if (__x.__has_val() != __y.__has_val()) { 1144bdd1243dSDimitry Andric return false; 1145bdd1243dSDimitry Andric } else { 11467a6dacacSDimitry Andric if (__x.__has_val()) { 11477a6dacacSDimitry Andric return __x.__val() == __y.__val(); 1148bdd1243dSDimitry Andric } else { 11497a6dacacSDimitry Andric return __x.__unex() == __y.__unex(); 1150bdd1243dSDimitry Andric } 1151bdd1243dSDimitry Andric } 1152bdd1243dSDimitry Andric } 1153bdd1243dSDimitry Andric 1154bdd1243dSDimitry Andric template <class _T2> 1155bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) { 11567a6dacacSDimitry Andric return __x.__has_val() && static_cast<bool>(__x.__val() == __v); 1157bdd1243dSDimitry Andric } 1158bdd1243dSDimitry Andric 1159bdd1243dSDimitry Andric template <class _E2> 1160bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) { 11617a6dacacSDimitry Andric return !__x.__has_val() && static_cast<bool>(__x.__unex() == __e.error()); 1162bdd1243dSDimitry Andric } 116306c3fb27SDimitry Andric }; 116406c3fb27SDimitry Andric 11657a6dacacSDimitry Andric template <class _Err> 11667a6dacacSDimitry Andric class __expected_void_base { 11677a6dacacSDimitry Andric struct __empty_t {}; 116806c3fb27SDimitry Andric // use named union because [[no_unique_address]] cannot be applied to an unnamed union, 116906c3fb27SDimitry Andric // also guaranteed elision into a potentially-overlapping subobject is unsettled (and 117006c3fb27SDimitry Andric // it's not clear that it's implementable, given that the function is allowed to clobber 117106c3fb27SDimitry Andric // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107. 11727a6dacacSDimitry Andric union __union_t { 11737a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = delete; 11747a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) 11757a6dacacSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 11767a6dacacSDimitry Andric = default; 11777a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = delete; 11787a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) 11797a6dacacSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 11807a6dacacSDimitry Andric = default; 11817a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete; 11827a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(__union_t&&) = delete; 11837a6dacacSDimitry Andric 11847a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t) : __empty_() {} 1185b121cb00SDimitry Andric 1186b121cb00SDimitry Andric template <class... _Args> 11877a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args) 1188b121cb00SDimitry Andric : __unex_(std::forward<_Args>(__args)...) {} 118906c3fb27SDimitry Andric 119006c3fb27SDimitry Andric template <class _Func, class... _Args> 119106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t( 11927a6dacacSDimitry Andric __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args) 119306c3fb27SDimitry Andric : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {} 119406c3fb27SDimitry Andric 119506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 11967a6dacacSDimitry Andric requires(is_trivially_destructible_v<_Err>) 1197bdd1243dSDimitry Andric = default; 1198bdd1243dSDimitry Andric 11997a6dacacSDimitry Andric // __repr's destructor handles this 1200bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() 12017a6dacacSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 1202bdd1243dSDimitry Andric {} 1203bdd1243dSDimitry Andric 12047a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_; 12057a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_; 120606c3fb27SDimitry Andric }; 1207bdd1243dSDimitry Andric 12087a6dacacSDimitry Andric static constexpr bool __put_flag_in_tail = __fits_in_tail_padding<__union_t, bool>; 12097a6dacacSDimitry Andric static constexpr bool __allow_reusing_expected_tail_padding = !__put_flag_in_tail; 12107a6dacacSDimitry Andric 12117a6dacacSDimitry Andric struct __repr { 12127a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete; 12137a6dacacSDimitry Andric 12147a6dacacSDimitry Andric template <class... _Args> 12157a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag) : __union_(in_place, __tag), __has_val_(true) {} 12167a6dacacSDimitry Andric 12177a6dacacSDimitry Andric template <class... _Args> 12187a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args) 12197a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(false) {} 12207a6dacacSDimitry Andric 12217a6dacacSDimitry Andric template <class... _Args> 12227a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(std::__expected_construct_unexpected_from_invoke_tag __tag, 12237a6dacacSDimitry Andric _Args&&... __args) 12247a6dacacSDimitry Andric : __union_(in_place, __tag, std::forward<_Args>(__args)...), __has_val_(false) {} 12257a6dacacSDimitry Andric 12267a6dacacSDimitry Andric template <class _OtherUnion> 12277a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other) 12287a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 12297a6dacacSDimitry Andric : __union_(__conditional_no_unique_address_invoke_tag{}, 12307a6dacacSDimitry Andric [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }), 12317a6dacacSDimitry Andric __has_val_(__has_val) {} 12327a6dacacSDimitry Andric 12337a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete; 12347a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) 12357a6dacacSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 12367a6dacacSDimitry Andric = default; 12377a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete; 12387a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) 12397a6dacacSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 12407a6dacacSDimitry Andric = default; 12417a6dacacSDimitry Andric 12427a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete; 12437a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(__repr&&) = delete; 12447a6dacacSDimitry Andric 12457a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__repr() 12467a6dacacSDimitry Andric requires(is_trivially_destructible_v<_Err>) 12477a6dacacSDimitry Andric = default; 12487a6dacacSDimitry Andric 12497a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~__repr() 12507a6dacacSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 12517a6dacacSDimitry Andric { 12527a6dacacSDimitry Andric __destroy_union_member(); 12537a6dacacSDimitry Andric } 12547a6dacacSDimitry Andric 12557a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union() 12567a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding && is_trivially_destructible_v<_Err>) 12577a6dacacSDimitry Andric { 12587a6dacacSDimitry Andric std::destroy_at(&__union_.__v); 12597a6dacacSDimitry Andric } 12607a6dacacSDimitry Andric 12617a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union() 12627a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding && !is_trivially_destructible_v<_Err>) 12637a6dacacSDimitry Andric { 12647a6dacacSDimitry Andric __destroy_union_member(); 12657a6dacacSDimitry Andric std::destroy_at(&__union_.__v); 12667a6dacacSDimitry Andric } 12677a6dacacSDimitry Andric 12687a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t) 12697a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 12707a6dacacSDimitry Andric { 12717a6dacacSDimitry Andric std::construct_at(&__union_.__v, in_place); 12727a6dacacSDimitry Andric __has_val_ = true; 12737a6dacacSDimitry Andric } 12747a6dacacSDimitry Andric 12757a6dacacSDimitry Andric template <class... _Args> 12767a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args) 12777a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 12787a6dacacSDimitry Andric { 12797a6dacacSDimitry Andric std::construct_at(&__union_.__v, unexpect, std::forward<_Args>(__args)...); 12807a6dacacSDimitry Andric __has_val_ = false; 12817a6dacacSDimitry Andric } 12827a6dacacSDimitry Andric 12837a6dacacSDimitry Andric private: 12847a6dacacSDimitry Andric template <class> 12857a6dacacSDimitry Andric friend class __expected_void_base; 12867a6dacacSDimitry Andric 12877a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member() 12887a6dacacSDimitry Andric requires(!is_trivially_destructible_v<_Err>) 12897a6dacacSDimitry Andric { 12907a6dacacSDimitry Andric if (!__has_val_) 12917a6dacacSDimitry Andric std::destroy_at(std::addressof(__union_.__v.__unex_)); 12927a6dacacSDimitry Andric } 12937a6dacacSDimitry Andric 12947a6dacacSDimitry Andric template <class _OtherUnion> 12957a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr __union_t __make_union(bool __has_val, _OtherUnion&& __other) 12967a6dacacSDimitry Andric requires(__allow_reusing_expected_tail_padding) 12977a6dacacSDimitry Andric { 12987a6dacacSDimitry Andric if (__has_val) 12997a6dacacSDimitry Andric return __union_t(in_place); 13007a6dacacSDimitry Andric else 13017a6dacacSDimitry Andric return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_); 13027a6dacacSDimitry Andric } 13037a6dacacSDimitry Andric 13047a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__put_flag_in_tail, __union_t> __union_; 13057a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_; 13067a6dacacSDimitry Andric }; 13077a6dacacSDimitry Andric 13087a6dacacSDimitry Andric template <class _OtherUnion> 13097a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other) 13107a6dacacSDimitry Andric requires(__put_flag_in_tail) 13117a6dacacSDimitry Andric { 13127a6dacacSDimitry Andric if (__has_val) 13137a6dacacSDimitry Andric return __repr(in_place); 13147a6dacacSDimitry Andric else 13157a6dacacSDimitry Andric return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_); 13167a6dacacSDimitry Andric } 13177a6dacacSDimitry Andric 13187a6dacacSDimitry Andric protected: 13197a6dacacSDimitry Andric template <class... _Args> 13207a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args) 13217a6dacacSDimitry Andric : __repr_(in_place, std::forward<_Args>(__args)...) {} 13227a6dacacSDimitry Andric 13237a6dacacSDimitry Andric template <class _OtherUnion> 13247a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(bool __has_val, _OtherUnion&& __other) 13257a6dacacSDimitry Andric requires(__put_flag_in_tail) 13267a6dacacSDimitry Andric : __repr_(__conditional_no_unique_address_invoke_tag{}, 13277a6dacacSDimitry Andric [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {} 13287a6dacacSDimitry Andric 13297a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() { 13307a6dacacSDimitry Andric if constexpr (__put_flag_in_tail) 13317a6dacacSDimitry Andric std::destroy_at(&__repr_.__v); 13327a6dacacSDimitry Andric else 13337a6dacacSDimitry Andric __repr_.__v.__destroy_union(); 13347a6dacacSDimitry Andric } 13357a6dacacSDimitry Andric 13367a6dacacSDimitry Andric template <class _Tag, class... _Args> 13377a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args) { 13387a6dacacSDimitry Andric if constexpr (__put_flag_in_tail) 13397a6dacacSDimitry Andric std::construct_at(&__repr_.__v, __tag, std::forward<_Args>(__args)...); 13407a6dacacSDimitry Andric else 13417a6dacacSDimitry Andric __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...); 13427a6dacacSDimitry Andric } 13437a6dacacSDimitry Andric 13447a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; } 13457a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; } 13467a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; } 13477a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_; } 13487a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; } 13497a6dacacSDimitry Andric 13507a6dacacSDimitry Andric private: 13517a6dacacSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__allow_reusing_expected_tail_padding, __repr> __repr_; 1352bdd1243dSDimitry Andric }; 1353bdd1243dSDimitry Andric 1354bdd1243dSDimitry Andric template <class _Tp, class _Err> 1355bdd1243dSDimitry Andric requires is_void_v<_Tp> 13567a6dacacSDimitry Andric class expected<_Tp, _Err> : private __expected_void_base<_Err> { 1357bdd1243dSDimitry Andric static_assert(__valid_std_unexpected<_Err>::value, 1358bdd1243dSDimitry Andric "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a " 1359bdd1243dSDimitry Andric "valid argument for unexpected<E> is ill-formed"); 1360bdd1243dSDimitry Andric 1361bdd1243dSDimitry Andric template <class, class> 1362bdd1243dSDimitry Andric friend class expected; 1363bdd1243dSDimitry Andric 1364bdd1243dSDimitry Andric template <class _Up, class _OtherErr, class _OtherErrQual> 1365bdd1243dSDimitry Andric using __can_convert = 1366bdd1243dSDimitry Andric _And< is_void<_Up>, 1367bdd1243dSDimitry Andric is_constructible<_Err, _OtherErrQual>, 1368bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>, 1369bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>, 1370bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>, 1371bdd1243dSDimitry Andric _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>; 1372bdd1243dSDimitry Andric 13737a6dacacSDimitry Andric using __base = __expected_void_base<_Err>; 13747a6dacacSDimitry Andric 1375bdd1243dSDimitry Andric public: 1376bdd1243dSDimitry Andric using value_type = _Tp; 1377bdd1243dSDimitry Andric using error_type = _Err; 1378bdd1243dSDimitry Andric using unexpected_type = unexpected<_Err>; 1379bdd1243dSDimitry Andric 1380bdd1243dSDimitry Andric template <class _Up> 1381bdd1243dSDimitry Andric using rebind = expected<_Up, error_type>; 1382bdd1243dSDimitry Andric 1383bdd1243dSDimitry Andric // [expected.void.ctor], constructors 13847a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __base(in_place) {} 1385bdd1243dSDimitry Andric 1386bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete; 1387bdd1243dSDimitry Andric 1388bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) 1389bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>) 1390bdd1243dSDimitry Andric = default; 1391bdd1243dSDimitry Andric 1392cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) noexcept( 1393cb14a3feSDimitry Andric is_nothrow_copy_constructible_v<_Err>) // strengthened 1394bdd1243dSDimitry Andric requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>) 13957a6dacacSDimitry Andric : __base(__rhs.__has_val(), __rhs.__union()) {} 1396bdd1243dSDimitry Andric 1397bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&) 1398bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>) 1399bdd1243dSDimitry Andric = default; 1400bdd1243dSDimitry Andric 1401cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) noexcept(is_nothrow_move_constructible_v<_Err>) 1402bdd1243dSDimitry Andric requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>) 14037a6dacacSDimitry Andric : __base(__rhs.__has_val(), std::move(__rhs.__union())) {} 1404bdd1243dSDimitry Andric 1405bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 1406bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value 1407bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) 1408cb14a3feSDimitry Andric expected(const expected<_Up, _OtherErr>& __rhs) noexcept( 1409cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 14107a6dacacSDimitry Andric : __base(__rhs.__has_val(), __rhs.__union()) {} 1411bdd1243dSDimitry Andric 1412bdd1243dSDimitry Andric template <class _Up, class _OtherErr> 1413bdd1243dSDimitry Andric requires __can_convert<_Up, _OtherErr, _OtherErr>::value 1414bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 1415cb14a3feSDimitry Andric expected(expected<_Up, _OtherErr>&& __rhs) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 14167a6dacacSDimitry Andric : __base(__rhs.__has_val(), std::move(__rhs.__union())) {} 1417bdd1243dSDimitry Andric 1418bdd1243dSDimitry Andric template <class _OtherErr> 1419bdd1243dSDimitry Andric requires is_constructible_v<_Err, const _OtherErr&> 1420cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected( 1421cb14a3feSDimitry Andric const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened 14227a6dacacSDimitry Andric : __base(unexpect, __unex.error()) {} 1423bdd1243dSDimitry Andric 1424bdd1243dSDimitry Andric template <class _OtherErr> 1425bdd1243dSDimitry Andric requires is_constructible_v<_Err, _OtherErr> 1426bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>) 1427cb14a3feSDimitry Andric expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened 14287a6dacacSDimitry Andric : __base(unexpect, std::move(__unex.error())) {} 1429bdd1243dSDimitry Andric 14307a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __base(in_place) {} 1431bdd1243dSDimitry Andric 1432bdd1243dSDimitry Andric template <class... _Args> 1433bdd1243dSDimitry Andric requires is_constructible_v<_Err, _Args...> 1434cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept( 1435cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, _Args...>) // strengthened 14367a6dacacSDimitry Andric : __base(unexpect, std::forward<_Args>(__args)...) {} 1437bdd1243dSDimitry Andric 1438bdd1243dSDimitry Andric template <class _Up, class... _Args> 1439bdd1243dSDimitry Andric requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... > 1440cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept( 1441cb14a3feSDimitry Andric is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened 14427a6dacacSDimitry Andric : __base(unexpect, __il, std::forward<_Args>(__args)...) {} 1443bdd1243dSDimitry Andric 144406c3fb27SDimitry Andric private: 144506c3fb27SDimitry Andric template <class _Func, class... _Args> 144606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit expected( 144706c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args) 14487a6dacacSDimitry Andric : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {} 144906c3fb27SDimitry Andric 145006c3fb27SDimitry Andric public: 1451bdd1243dSDimitry Andric // [expected.void.dtor], destructor 1452bdd1243dSDimitry Andric 14537a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr ~expected() = default; 1454bdd1243dSDimitry Andric 14557a6dacacSDimitry Andric private: 14567a6dacacSDimitry Andric template <class... _Args> 14577a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(unexpect_t, _Args&&... __args) { 14587a6dacacSDimitry Andric _LIBCPP_ASSERT_INTERNAL(this->__has_val(), "__reinit_expected(unexpect_t, ...) needs value to be set"); 14597a6dacacSDimitry Andric 14607a6dacacSDimitry Andric this->__destroy(); 14617a6dacacSDimitry Andric auto __trans = std::__make_exception_guard([&] { this->__construct(in_place); }); 14627a6dacacSDimitry Andric this->__construct(unexpect, std::forward<_Args>(__args)...); 14637a6dacacSDimitry Andric __trans.__complete(); 1464bdd1243dSDimitry Andric } 1465bdd1243dSDimitry Andric 14667a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(in_place_t) { 14677a6dacacSDimitry Andric _LIBCPP_ASSERT_INTERNAL(!this->__has_val(), "__reinit_expected(in_place_t, ...) needs value to be unset"); 14687a6dacacSDimitry Andric 14697a6dacacSDimitry Andric this->__destroy(); 14707a6dacacSDimitry Andric this->__construct(in_place); 14717a6dacacSDimitry Andric } 14727a6dacacSDimitry Andric 14737a6dacacSDimitry Andric public: 1474bdd1243dSDimitry Andric // [expected.void.assign], assignment 1475bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete; 1476bdd1243dSDimitry Andric 1477cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept( 1478cb14a3feSDimitry Andric is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened 1479bdd1243dSDimitry Andric requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>) 1480bdd1243dSDimitry Andric { 14817a6dacacSDimitry Andric if (this->__has_val()) { 14827a6dacacSDimitry Andric if (!__rhs.__has_val()) { 14837a6dacacSDimitry Andric __reinit_expected(unexpect, __rhs.__unex()); 1484bdd1243dSDimitry Andric } 1485bdd1243dSDimitry Andric } else { 14867a6dacacSDimitry Andric if (__rhs.__has_val()) { 14877a6dacacSDimitry Andric __reinit_expected(in_place); 1488bdd1243dSDimitry Andric } else { 14897a6dacacSDimitry Andric this->__unex() = __rhs.__unex(); 1490bdd1243dSDimitry Andric } 1491bdd1243dSDimitry Andric } 1492bdd1243dSDimitry Andric return *this; 1493bdd1243dSDimitry Andric } 1494bdd1243dSDimitry Andric 1495bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete; 1496bdd1243dSDimitry Andric 1497cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& 1498cb14a3feSDimitry Andric operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>) 1499cb14a3feSDimitry Andric requires(is_move_assignable_v<_Err> && is_move_constructible_v<_Err>) 1500bdd1243dSDimitry Andric { 15017a6dacacSDimitry Andric if (this->__has_val()) { 15027a6dacacSDimitry Andric if (!__rhs.__has_val()) { 15037a6dacacSDimitry Andric __reinit_expected(unexpect, std::move(__rhs.__unex())); 1504bdd1243dSDimitry Andric } 1505bdd1243dSDimitry Andric } else { 15067a6dacacSDimitry Andric if (__rhs.__has_val()) { 15077a6dacacSDimitry Andric __reinit_expected(in_place); 1508bdd1243dSDimitry Andric } else { 15097a6dacacSDimitry Andric this->__unex() = std::move(__rhs.__unex()); 1510bdd1243dSDimitry Andric } 1511bdd1243dSDimitry Andric } 1512bdd1243dSDimitry Andric return *this; 1513bdd1243dSDimitry Andric } 1514bdd1243dSDimitry Andric 1515bdd1243dSDimitry Andric template <class _OtherErr> 1516bdd1243dSDimitry Andric requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>) 1517bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) { 15187a6dacacSDimitry Andric if (this->__has_val()) { 15197a6dacacSDimitry Andric __reinit_expected(unexpect, __un.error()); 1520bdd1243dSDimitry Andric } else { 15217a6dacacSDimitry Andric this->__unex() = __un.error(); 1522bdd1243dSDimitry Andric } 1523bdd1243dSDimitry Andric return *this; 1524bdd1243dSDimitry Andric } 1525bdd1243dSDimitry Andric 1526bdd1243dSDimitry Andric template <class _OtherErr> 1527bdd1243dSDimitry Andric requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>) 1528bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) { 15297a6dacacSDimitry Andric if (this->__has_val()) { 15307a6dacacSDimitry Andric __reinit_expected(unexpect, std::move(__un.error())); 1531bdd1243dSDimitry Andric } else { 15327a6dacacSDimitry Andric this->__unex() = std::move(__un.error()); 1533bdd1243dSDimitry Andric } 1534bdd1243dSDimitry Andric return *this; 1535bdd1243dSDimitry Andric } 1536bdd1243dSDimitry Andric 1537bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept { 15387a6dacacSDimitry Andric if (!this->__has_val()) { 15397a6dacacSDimitry Andric __reinit_expected(in_place); 1540bdd1243dSDimitry Andric } 1541bdd1243dSDimitry Andric } 1542bdd1243dSDimitry Andric 1543bdd1243dSDimitry Andric // [expected.void.swap], swap 1544cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 1545cb14a3feSDimitry Andric swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>) 1546bdd1243dSDimitry Andric requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>) 1547bdd1243dSDimitry Andric { 15487a6dacacSDimitry Andric auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) { 15497a6dacacSDimitry Andric // May throw, but will re-engage `__with_val` in that case. 15507a6dacacSDimitry Andric __with_val.__reinit_expected(unexpect, std::move(__with_err.__unex())); 15517a6dacacSDimitry Andric // Will not throw. 15527a6dacacSDimitry Andric __with_err.__reinit_expected(in_place); 1553bdd1243dSDimitry Andric }; 1554bdd1243dSDimitry Andric 15557a6dacacSDimitry Andric if (this->__has_val()) { 15567a6dacacSDimitry Andric if (!__rhs.__has_val()) { 1557bdd1243dSDimitry Andric __swap_val_unex_impl(*this, __rhs); 1558bdd1243dSDimitry Andric } 1559bdd1243dSDimitry Andric } else { 15607a6dacacSDimitry Andric if (__rhs.__has_val()) { 1561bdd1243dSDimitry Andric __swap_val_unex_impl(__rhs, *this); 1562bdd1243dSDimitry Andric } else { 1563bdd1243dSDimitry Andric using std::swap; 15647a6dacacSDimitry Andric swap(this->__unex(), __rhs.__unex()); 1565bdd1243dSDimitry Andric } 1566bdd1243dSDimitry Andric } 1567bdd1243dSDimitry Andric } 1568bdd1243dSDimitry Andric 1569cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y))) 1570bdd1243dSDimitry Andric requires requires { __x.swap(__y); } 1571bdd1243dSDimitry Andric { 1572bdd1243dSDimitry Andric __x.swap(__y); 1573bdd1243dSDimitry Andric } 1574bdd1243dSDimitry Andric 1575bdd1243dSDimitry Andric // [expected.void.obs], observers 15767a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); } 1577bdd1243dSDimitry Andric 15787a6dacacSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } 1579bdd1243dSDimitry Andric 1580bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { 15817a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 15827a6dacacSDimitry Andric this->__has_val(), "expected::operator* requires the expected to contain a value"); 1583bdd1243dSDimitry Andric } 1584bdd1243dSDimitry Andric 1585bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() const& { 15867a6dacacSDimitry Andric static_assert(is_copy_constructible_v<_Err>); 15877a6dacacSDimitry Andric if (!this->__has_val()) { 15887a6dacacSDimitry Andric std::__throw_bad_expected_access<_Err>(this->__unex()); 1589bdd1243dSDimitry Andric } 1590bdd1243dSDimitry Andric } 1591bdd1243dSDimitry Andric 1592bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void value() && { 15937a6dacacSDimitry Andric static_assert(is_copy_constructible_v<_Err> && is_move_constructible_v<_Err>); 15947a6dacacSDimitry Andric if (!this->__has_val()) { 15957a6dacacSDimitry Andric std::__throw_bad_expected_access<_Err>(std::move(this->__unex())); 1596bdd1243dSDimitry Andric } 1597bdd1243dSDimitry Andric } 1598bdd1243dSDimitry Andric 1599bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { 16007a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 16017a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 16027a6dacacSDimitry Andric return this->__unex(); 1603bdd1243dSDimitry Andric } 1604bdd1243dSDimitry Andric 1605bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { 16067a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 16077a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 16087a6dacacSDimitry Andric return this->__unex(); 1609bdd1243dSDimitry Andric } 1610bdd1243dSDimitry Andric 1611bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { 16127a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 16137a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 16147a6dacacSDimitry Andric return std::move(this->__unex()); 1615bdd1243dSDimitry Andric } 1616bdd1243dSDimitry Andric 1617bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { 16187a6dacacSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 16197a6dacacSDimitry Andric !this->__has_val(), "expected::error requires the expected to contain an error"); 16207a6dacacSDimitry Andric return std::move(this->__unex()); 1621bdd1243dSDimitry Andric } 1622bdd1243dSDimitry Andric 162306c3fb27SDimitry Andric template <class _Up = _Err> 162406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { 162506c3fb27SDimitry Andric static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); 162606c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 162706c3fb27SDimitry Andric if (has_value()) { 162806c3fb27SDimitry Andric return std::forward<_Up>(__error); 162906c3fb27SDimitry Andric } 163006c3fb27SDimitry Andric return error(); 163106c3fb27SDimitry Andric } 163206c3fb27SDimitry Andric 163306c3fb27SDimitry Andric template <class _Up = _Err> 163406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { 163506c3fb27SDimitry Andric static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); 163606c3fb27SDimitry Andric static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); 163706c3fb27SDimitry Andric if (has_value()) { 163806c3fb27SDimitry Andric return std::forward<_Up>(__error); 163906c3fb27SDimitry Andric } 164006c3fb27SDimitry Andric return std::move(error()); 164106c3fb27SDimitry Andric } 164206c3fb27SDimitry Andric 164306c3fb27SDimitry Andric // [expected.void.monadic], monadic 164406c3fb27SDimitry Andric template <class _Func> 164506c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 164606c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { 164706c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 164806c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 164906c3fb27SDimitry Andric static_assert( 165006c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 165106c3fb27SDimitry Andric if (has_value()) { 165206c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 165306c3fb27SDimitry Andric } 165406c3fb27SDimitry Andric return _Up(unexpect, error()); 165506c3fb27SDimitry Andric } 165606c3fb27SDimitry Andric 165706c3fb27SDimitry Andric template <class _Func> 165806c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 165906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { 166006c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 166106c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 166206c3fb27SDimitry Andric static_assert( 166306c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 166406c3fb27SDimitry Andric if (has_value()) { 166506c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 166606c3fb27SDimitry Andric } 166706c3fb27SDimitry Andric return _Up(unexpect, error()); 166806c3fb27SDimitry Andric } 166906c3fb27SDimitry Andric 167006c3fb27SDimitry Andric template <class _Func> 167106c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 167206c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { 167306c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 167406c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 167506c3fb27SDimitry Andric static_assert( 167606c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 167706c3fb27SDimitry Andric if (has_value()) { 167806c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 167906c3fb27SDimitry Andric } 168006c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 168106c3fb27SDimitry Andric } 168206c3fb27SDimitry Andric 168306c3fb27SDimitry Andric template <class _Func> 168406c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 168506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { 168606c3fb27SDimitry Andric using _Up = remove_cvref_t<invoke_result_t<_Func>>; 168706c3fb27SDimitry Andric static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected"); 168806c3fb27SDimitry Andric static_assert( 168906c3fb27SDimitry Andric is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected"); 169006c3fb27SDimitry Andric if (has_value()) { 169106c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f)); 169206c3fb27SDimitry Andric } 169306c3fb27SDimitry Andric return _Up(unexpect, std::move(error())); 169406c3fb27SDimitry Andric } 169506c3fb27SDimitry Andric 169606c3fb27SDimitry Andric template <class _Func> 169706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { 169806c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; 169906c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 170006c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 170106c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 170206c3fb27SDimitry Andric if (has_value()) { 170306c3fb27SDimitry Andric return _Gp(); 170406c3fb27SDimitry Andric } 170506c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 170606c3fb27SDimitry Andric } 170706c3fb27SDimitry Andric 170806c3fb27SDimitry Andric template <class _Func> 170906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { 171006c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; 171106c3fb27SDimitry Andric static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); 171206c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 171306c3fb27SDimitry Andric "The result of f(error()) must have the same value_type as this expected"); 171406c3fb27SDimitry Andric if (has_value()) { 171506c3fb27SDimitry Andric return _Gp(); 171606c3fb27SDimitry Andric } 171706c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), error()); 171806c3fb27SDimitry Andric } 171906c3fb27SDimitry Andric 172006c3fb27SDimitry Andric template <class _Func> 172106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { 172206c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; 1723cb14a3feSDimitry Andric static_assert( 1724cb14a3feSDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 172506c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 172606c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 172706c3fb27SDimitry Andric if (has_value()) { 172806c3fb27SDimitry Andric return _Gp(); 172906c3fb27SDimitry Andric } 173006c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 173106c3fb27SDimitry Andric } 173206c3fb27SDimitry Andric 173306c3fb27SDimitry Andric template <class _Func> 173406c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { 173506c3fb27SDimitry Andric using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; 1736cb14a3feSDimitry Andric static_assert( 1737cb14a3feSDimitry Andric __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); 173806c3fb27SDimitry Andric static_assert(is_same_v<typename _Gp::value_type, _Tp>, 173906c3fb27SDimitry Andric "The result of f(std::move(error())) must have the same value_type as this expected"); 174006c3fb27SDimitry Andric if (has_value()) { 174106c3fb27SDimitry Andric return _Gp(); 174206c3fb27SDimitry Andric } 174306c3fb27SDimitry Andric return std::invoke(std::forward<_Func>(__f), std::move(error())); 174406c3fb27SDimitry Andric } 174506c3fb27SDimitry Andric 174606c3fb27SDimitry Andric template <class _Func> 174706c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&> 174806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { 174906c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 175006c3fb27SDimitry Andric if (!has_value()) { 175106c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 175206c3fb27SDimitry Andric } 175306c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 175406c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 175506c3fb27SDimitry Andric } else { 175606c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 175706c3fb27SDimitry Andric return expected<_Up, _Err>(); 175806c3fb27SDimitry Andric } 175906c3fb27SDimitry Andric } 176006c3fb27SDimitry Andric 176106c3fb27SDimitry Andric template <class _Func> 176206c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&> 176306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { 176406c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 176506c3fb27SDimitry Andric if (!has_value()) { 176606c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, error()); 176706c3fb27SDimitry Andric } 176806c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 176906c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 177006c3fb27SDimitry Andric } else { 177106c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 177206c3fb27SDimitry Andric return expected<_Up, _Err>(); 177306c3fb27SDimitry Andric } 177406c3fb27SDimitry Andric } 177506c3fb27SDimitry Andric 177606c3fb27SDimitry Andric template <class _Func> 177706c3fb27SDimitry Andric requires is_constructible_v<_Err, _Err&&> 177806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { 177906c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 178006c3fb27SDimitry Andric if (!has_value()) { 178106c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 178206c3fb27SDimitry Andric } 178306c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 178406c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 178506c3fb27SDimitry Andric } else { 178606c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 178706c3fb27SDimitry Andric return expected<_Up, _Err>(); 178806c3fb27SDimitry Andric } 178906c3fb27SDimitry Andric } 179006c3fb27SDimitry Andric 179106c3fb27SDimitry Andric template <class _Func> 179206c3fb27SDimitry Andric requires is_constructible_v<_Err, const _Err&&> 179306c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { 179406c3fb27SDimitry Andric using _Up = remove_cv_t<invoke_result_t<_Func>>; 179506c3fb27SDimitry Andric if (!has_value()) { 179606c3fb27SDimitry Andric return expected<_Up, _Err>(unexpect, std::move(error())); 179706c3fb27SDimitry Andric } 179806c3fb27SDimitry Andric if constexpr (!is_void_v<_Up>) { 179906c3fb27SDimitry Andric return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f)); 180006c3fb27SDimitry Andric } else { 180106c3fb27SDimitry Andric std::invoke(std::forward<_Func>(__f)); 180206c3fb27SDimitry Andric return expected<_Up, _Err>(); 180306c3fb27SDimitry Andric } 180406c3fb27SDimitry Andric } 180506c3fb27SDimitry Andric 180606c3fb27SDimitry Andric template <class _Func> 180706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { 180806c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; 180906c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 181006c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 181106c3fb27SDimitry Andric if (has_value()) { 181206c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 181306c3fb27SDimitry Andric } 181406c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 181506c3fb27SDimitry Andric } 181606c3fb27SDimitry Andric 181706c3fb27SDimitry Andric template <class _Func> 181806c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { 181906c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; 182006c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 182106c3fb27SDimitry Andric "The result of f(error()) must be a valid template argument for unexpected"); 182206c3fb27SDimitry Andric if (has_value()) { 182306c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 182406c3fb27SDimitry Andric } 182506c3fb27SDimitry Andric return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error()); 182606c3fb27SDimitry Andric } 182706c3fb27SDimitry Andric 182806c3fb27SDimitry Andric template <class _Func> 182906c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { 183006c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; 183106c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 183206c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 183306c3fb27SDimitry Andric if (has_value()) { 183406c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 183506c3fb27SDimitry Andric } 183606c3fb27SDimitry Andric return expected<_Tp, _Gp>( 183706c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 183806c3fb27SDimitry Andric } 183906c3fb27SDimitry Andric 184006c3fb27SDimitry Andric template <class _Func> 184106c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { 184206c3fb27SDimitry Andric using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; 184306c3fb27SDimitry Andric static_assert(__valid_std_unexpected<_Gp>::value, 184406c3fb27SDimitry Andric "The result of f(std::move(error())) must be a valid template argument for unexpected"); 184506c3fb27SDimitry Andric if (has_value()) { 184606c3fb27SDimitry Andric return expected<_Tp, _Gp>(); 184706c3fb27SDimitry Andric } 184806c3fb27SDimitry Andric return expected<_Tp, _Gp>( 184906c3fb27SDimitry Andric __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error())); 185006c3fb27SDimitry Andric } 185106c3fb27SDimitry Andric 1852bdd1243dSDimitry Andric // [expected.void.eq], equality operators 1853bdd1243dSDimitry Andric template <class _T2, class _E2> 1854bdd1243dSDimitry Andric requires is_void_v<_T2> 1855bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) { 18567a6dacacSDimitry Andric if (__x.__has_val() != __y.__has_val()) { 1857bdd1243dSDimitry Andric return false; 1858bdd1243dSDimitry Andric } else { 18597a6dacacSDimitry Andric return __x.__has_val() || static_cast<bool>(__x.__unex() == __y.__unex()); 1860bdd1243dSDimitry Andric } 1861bdd1243dSDimitry Andric } 1862bdd1243dSDimitry Andric 1863bdd1243dSDimitry Andric template <class _E2> 1864bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) { 18657a6dacacSDimitry Andric return !__x.__has_val() && static_cast<bool>(__x.__unex() == __y.error()); 1866bdd1243dSDimitry Andric } 1867bdd1243dSDimitry Andric }; 1868bdd1243dSDimitry Andric 1869bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1870bdd1243dSDimitry Andric 1871bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23 1872bdd1243dSDimitry Andric 187306c3fb27SDimitry Andric _LIBCPP_POP_MACROS 187406c3fb27SDimitry Andric 1875bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H 1876