xref: /freebsd-src/contrib/llvm-project/libcxx/include/__expected/expected.h (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
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_copy_assignable.h>
27bdd1243dSDimitry Andric #include <__type_traits/is_copy_constructible.h>
28bdd1243dSDimitry Andric #include <__type_traits/is_default_constructible.h>
29bdd1243dSDimitry Andric #include <__type_traits/is_function.h>
30bdd1243dSDimitry Andric #include <__type_traits/is_move_assignable.h>
31bdd1243dSDimitry Andric #include <__type_traits/is_move_constructible.h>
32bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
33bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_assignable.h>
34bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_constructible.h>
35bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_default_constructible.h>
36bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_assignable.h>
37bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_constructible.h>
38bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
39bdd1243dSDimitry Andric #include <__type_traits/is_same.h>
40bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h>
41bdd1243dSDimitry Andric #include <__type_traits/is_trivially_copy_constructible.h>
42bdd1243dSDimitry Andric #include <__type_traits/is_trivially_destructible.h>
43bdd1243dSDimitry Andric #include <__type_traits/is_trivially_move_constructible.h>
44bdd1243dSDimitry Andric #include <__type_traits/is_void.h>
45bdd1243dSDimitry Andric #include <__type_traits/lazy.h>
46bdd1243dSDimitry Andric #include <__type_traits/negation.h>
47bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h>
48bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
4906c3fb27SDimitry Andric #include <__utility/as_const.h>
50bdd1243dSDimitry Andric #include <__utility/exception_guard.h>
51bdd1243dSDimitry Andric #include <__utility/forward.h>
52bdd1243dSDimitry Andric #include <__utility/in_place.h>
53bdd1243dSDimitry Andric #include <__utility/move.h>
54bdd1243dSDimitry Andric #include <__utility/swap.h>
5506c3fb27SDimitry Andric #include <__verbose_abort>
56bdd1243dSDimitry Andric #include <initializer_list>
57bdd1243dSDimitry Andric 
58bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
59bdd1243dSDimitry Andric #  pragma GCC system_header
60bdd1243dSDimitry Andric #endif
61bdd1243dSDimitry Andric 
6206c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
6306c3fb27SDimitry Andric #include <__undef_macros>
6406c3fb27SDimitry Andric 
65bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 23
66bdd1243dSDimitry Andric 
67bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
68bdd1243dSDimitry Andric 
6906c3fb27SDimitry Andric template <class _Tp, class _Err>
7006c3fb27SDimitry Andric class expected;
7106c3fb27SDimitry Andric 
7206c3fb27SDimitry Andric template <class _Tp>
7306c3fb27SDimitry Andric struct __is_std_expected : false_type {};
7406c3fb27SDimitry Andric 
7506c3fb27SDimitry Andric template <class _Tp, class _Err>
7606c3fb27SDimitry Andric struct __is_std_expected<expected<_Tp, _Err>> : true_type {};
7706c3fb27SDimitry Andric 
7806c3fb27SDimitry Andric struct __expected_construct_in_place_from_invoke_tag {};
7906c3fb27SDimitry Andric struct __expected_construct_unexpected_from_invoke_tag {};
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric template <class _Err, class _Arg>
82bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
8306c3fb27SDimitry Andric #  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
84bdd1243dSDimitry Andric   throw bad_expected_access<_Err>(std::forward<_Arg>(__arg));
85bdd1243dSDimitry Andric #  else
86bdd1243dSDimitry Andric   (void)__arg;
8706c3fb27SDimitry Andric   _LIBCPP_VERBOSE_ABORT("bad_expected_access was thrown in -fno-exceptions mode");
88bdd1243dSDimitry Andric #  endif
89bdd1243dSDimitry Andric }
90bdd1243dSDimitry Andric 
91bdd1243dSDimitry Andric template <class _Tp, class _Err>
92bdd1243dSDimitry Andric class expected {
93*cb14a3feSDimitry Andric   static_assert(!is_reference_v<_Tp> && !is_function_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, in_place_t> &&
94*cb14a3feSDimitry Andric                     !is_same_v<remove_cv_t<_Tp>, unexpect_t> && !__is_std_unexpected<remove_cv_t<_Tp>>::value &&
95*cb14a3feSDimitry Andric                     __valid_std_unexpected<_Err>::value,
96bdd1243dSDimitry Andric                 "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a "
97bdd1243dSDimitry Andric                 "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a "
98bdd1243dSDimitry Andric                 "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the "
99bdd1243dSDimitry Andric                 "definition of the template expected<T, E> with a type for the E parameter that is not a valid "
100bdd1243dSDimitry Andric                 "template argument for unexpected is ill-formed.");
101bdd1243dSDimitry Andric 
102bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
103bdd1243dSDimitry Andric   friend class expected;
104bdd1243dSDimitry Andric 
105bdd1243dSDimitry Andric public:
106bdd1243dSDimitry Andric   using value_type      = _Tp;
107bdd1243dSDimitry Andric   using error_type      = _Err;
108bdd1243dSDimitry Andric   using unexpected_type = unexpected<_Err>;
109bdd1243dSDimitry Andric 
110bdd1243dSDimitry Andric   template <class _Up>
111bdd1243dSDimitry Andric   using rebind = expected<_Up, error_type>;
112bdd1243dSDimitry Andric 
113bdd1243dSDimitry Andric   // [expected.object.ctor], constructors
114*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
115bdd1243dSDimitry Andric     requires is_default_constructible_v<_Tp>
116b121cb00SDimitry Andric       : __union_(std::in_place), __has_val_(true) {}
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
119bdd1243dSDimitry Andric 
120bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
121*cb14a3feSDimitry Andric     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Tp> &&
122bdd1243dSDimitry Andric              is_trivially_copy_constructible_v<_Err>)
123bdd1243dSDimitry Andric   = default;
124bdd1243dSDimitry Andric 
125*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other) noexcept(
126*cb14a3feSDimitry Andric       is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
127bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
128bdd1243dSDimitry Andric              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
129b121cb00SDimitry Andric       : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {}
130bdd1243dSDimitry Andric 
131bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
132*cb14a3feSDimitry Andric     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Tp> &&
133*cb14a3feSDimitry Andric              is_trivially_move_constructible_v<_Err>)
134bdd1243dSDimitry Andric   = default;
135bdd1243dSDimitry Andric 
136*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other) noexcept(
137*cb14a3feSDimitry Andric       is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
138bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
139bdd1243dSDimitry Andric              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
140b121cb00SDimitry Andric       : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {}
141bdd1243dSDimitry Andric 
142bdd1243dSDimitry Andric private:
143bdd1243dSDimitry Andric   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
144bdd1243dSDimitry Andric   using __can_convert =
145bdd1243dSDimitry Andric       _And< is_constructible<_Tp, _UfQual>,
146bdd1243dSDimitry Andric             is_constructible<_Err, _OtherErrQual>,
1475f757f3fSDimitry Andric             _If<_Not<is_same<remove_cv_t<_Tp>, bool>>::value,
1485f757f3fSDimitry Andric                 _And< _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
149bdd1243dSDimitry Andric                       _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
150bdd1243dSDimitry Andric                       _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
151bdd1243dSDimitry Andric                       _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
152bdd1243dSDimitry Andric                       _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>,
153bdd1243dSDimitry Andric                       _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>,
154bdd1243dSDimitry Andric                       _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>,
1555f757f3fSDimitry Andric                       _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>>,
1565f757f3fSDimitry Andric                 true_type>,
157bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
158bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
159bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
160bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >;
161bdd1243dSDimitry Andric 
16206c3fb27SDimitry Andric   template <class _Func, class... _Args>
16306c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
16406c3fb27SDimitry Andric       std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
16506c3fb27SDimitry Andric       : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {}
16606c3fb27SDimitry Andric 
16706c3fb27SDimitry Andric   template <class _Func, class... _Args>
16806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
16906c3fb27SDimitry Andric       std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
17006c3fb27SDimitry Andric       : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {}
171bdd1243dSDimitry Andric 
172bdd1243dSDimitry Andric public:
173bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
174bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value
175bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> ||
176bdd1243dSDimitry Andric                                            !is_convertible_v<const _OtherErr&, _Err>)
177*cb14a3feSDimitry Andric       expected(const expected<_Up, _OtherErr>& __other) noexcept(
178*cb14a3feSDimitry Andric           is_nothrow_constructible_v<_Tp, const _Up&> &&
179bdd1243dSDimitry Andric           is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
180b121cb00SDimitry Andric       : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {}
181bdd1243dSDimitry Andric 
182bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
183bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
184bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
185*cb14a3feSDimitry Andric       expected(expected<_Up, _OtherErr>&& __other) noexcept(
186*cb14a3feSDimitry Andric           is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
187b121cb00SDimitry Andric       : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {}
188bdd1243dSDimitry Andric 
189bdd1243dSDimitry Andric   template <class _Up = _Tp>
190bdd1243dSDimitry Andric     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
1915f757f3fSDimitry Andric              is_constructible_v<_Tp, _Up> && !__is_std_unexpected<remove_cvref_t<_Up>>::value &&
1925f757f3fSDimitry Andric              (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
193bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
194b121cb00SDimitry Andric       expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
195b121cb00SDimitry Andric       : __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {}
196bdd1243dSDimitry Andric 
197bdd1243dSDimitry Andric   template <class _OtherErr>
198bdd1243dSDimitry Andric     requires is_constructible_v<_Err, const _OtherErr&>
199*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected(
200*cb14a3feSDimitry Andric       const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
201b121cb00SDimitry Andric       : __union_(std::unexpect, __unex.error()), __has_val_(false) {}
202bdd1243dSDimitry Andric 
203bdd1243dSDimitry Andric   template <class _OtherErr>
204bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _OtherErr>
205bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
206*cb14a3feSDimitry Andric       expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
207b121cb00SDimitry Andric       : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
208bdd1243dSDimitry Andric 
209bdd1243dSDimitry Andric   template <class... _Args>
210bdd1243dSDimitry Andric     requires is_constructible_v<_Tp, _Args...>
211*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args) noexcept(
212*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
213b121cb00SDimitry Andric       : __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {}
214bdd1243dSDimitry Andric 
215bdd1243dSDimitry Andric   template <class _Up, class... _Args>
216bdd1243dSDimitry Andric     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
217*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(
218*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
219b121cb00SDimitry Andric       : __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {}
220bdd1243dSDimitry Andric 
221bdd1243dSDimitry Andric   template <class... _Args>
222bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _Args...>
223*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept(
224*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Err, _Args...>) // strengthened
225b121cb00SDimitry Andric       : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
226bdd1243dSDimitry Andric 
227bdd1243dSDimitry Andric   template <class _Up, class... _Args>
228bdd1243dSDimitry Andric     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
229*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(
230*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
231b121cb00SDimitry Andric       : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
232bdd1243dSDimitry Andric 
233bdd1243dSDimitry Andric   // [expected.object.dtor], destructor
234bdd1243dSDimitry Andric 
235bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
236bdd1243dSDimitry Andric     requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
237bdd1243dSDimitry Andric   = default;
238bdd1243dSDimitry Andric 
239bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
240bdd1243dSDimitry Andric     requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
241bdd1243dSDimitry Andric   {
242bdd1243dSDimitry Andric     if (__has_val_) {
243bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
244bdd1243dSDimitry Andric     } else {
245bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
246bdd1243dSDimitry Andric     }
247bdd1243dSDimitry Andric   }
248bdd1243dSDimitry Andric 
249bdd1243dSDimitry Andric private:
250bdd1243dSDimitry Andric   template <class _T1, class _T2, class... _Args>
251bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) {
252bdd1243dSDimitry Andric     if constexpr (is_nothrow_constructible_v<_T1, _Args...>) {
253bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
254bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
255bdd1243dSDimitry Andric     } else if constexpr (is_nothrow_move_constructible_v<_T1>) {
256bdd1243dSDimitry Andric       _T1 __tmp(std::forward<_Args>(__args)...);
257bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
258bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::move(__tmp));
259bdd1243dSDimitry Andric     } else {
260bdd1243dSDimitry Andric       static_assert(
261bdd1243dSDimitry Andric           is_nothrow_move_constructible_v<_T2>,
262bdd1243dSDimitry Andric           "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
263bdd1243dSDimitry Andric           "be reverted to the previous state in case an exception is thrown during the assignment.");
264bdd1243dSDimitry Andric       _T2 __tmp(std::move(__oldval));
265bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
2661ac55f4cSDimitry Andric       auto __trans =
2671ac55f4cSDimitry Andric           std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
268bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
269bdd1243dSDimitry Andric       __trans.__complete();
270bdd1243dSDimitry Andric     }
271bdd1243dSDimitry Andric   }
272bdd1243dSDimitry Andric 
273bdd1243dSDimitry Andric public:
274bdd1243dSDimitry Andric   // [expected.object.assign], assignment
275bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
276bdd1243dSDimitry Andric 
277*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept(
278*cb14a3feSDimitry Andric       is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_assignable_v<_Err> &&
279bdd1243dSDimitry Andric       is_nothrow_copy_constructible_v<_Err>) // strengthened
280*cb14a3feSDimitry Andric     requires(is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp> && is_copy_assignable_v<_Err> &&
281bdd1243dSDimitry Andric              is_copy_constructible_v<_Err> &&
282*cb14a3feSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>))
283bdd1243dSDimitry Andric   {
284bdd1243dSDimitry Andric     if (__has_val_ && __rhs.__has_val_) {
285bdd1243dSDimitry Andric       __union_.__val_ = __rhs.__union_.__val_;
286bdd1243dSDimitry Andric     } else if (__has_val_) {
287bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_);
288bdd1243dSDimitry Andric     } else if (__rhs.__has_val_) {
289bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_);
290bdd1243dSDimitry Andric     } else {
291bdd1243dSDimitry Andric       __union_.__unex_ = __rhs.__union_.__unex_;
292bdd1243dSDimitry Andric     }
293bdd1243dSDimitry Andric     // note: only reached if no exception+rollback was done inside __reinit_expected
294bdd1243dSDimitry Andric     __has_val_ = __rhs.__has_val_;
295bdd1243dSDimitry Andric     return *this;
296bdd1243dSDimitry Andric   }
297bdd1243dSDimitry Andric 
298*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected&
299*cb14a3feSDimitry Andric   operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp> &&
300*cb14a3feSDimitry Andric                                        is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>)
301*cb14a3feSDimitry Andric     requires(is_move_constructible_v<_Tp> && is_move_assignable_v<_Tp> && is_move_constructible_v<_Err> &&
302bdd1243dSDimitry Andric              is_move_assignable_v<_Err> &&
303*cb14a3feSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>))
304bdd1243dSDimitry Andric   {
305bdd1243dSDimitry Andric     if (__has_val_ && __rhs.__has_val_) {
306bdd1243dSDimitry Andric       __union_.__val_ = std::move(__rhs.__union_.__val_);
307bdd1243dSDimitry Andric     } else if (__has_val_) {
308bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_));
309bdd1243dSDimitry Andric     } else if (__rhs.__has_val_) {
310bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_));
311bdd1243dSDimitry Andric     } else {
312bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__rhs.__union_.__unex_);
313bdd1243dSDimitry Andric     }
314bdd1243dSDimitry Andric     // note: only reached if no exception+rollback was done inside __reinit_expected
315bdd1243dSDimitry Andric     __has_val_ = __rhs.__has_val_;
316bdd1243dSDimitry Andric     return *this;
317bdd1243dSDimitry Andric   }
318bdd1243dSDimitry Andric 
319bdd1243dSDimitry Andric   template <class _Up = _Tp>
320bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v)
321*cb14a3feSDimitry Andric     requires(!is_same_v<expected, remove_cvref_t<_Up>> && !__is_std_unexpected<remove_cvref_t<_Up>>::value &&
322*cb14a3feSDimitry Andric              is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> &&
323*cb14a3feSDimitry Andric              (is_nothrow_constructible_v<_Tp, _Up> || is_nothrow_move_constructible_v<_Tp> ||
324bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Err>))
325bdd1243dSDimitry Andric   {
326bdd1243dSDimitry Andric     if (__has_val_) {
327bdd1243dSDimitry Andric       __union_.__val_ = std::forward<_Up>(__v);
328bdd1243dSDimitry Andric     } else {
329bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v));
330bdd1243dSDimitry Andric       __has_val_ = true;
331bdd1243dSDimitry Andric     }
332bdd1243dSDimitry Andric     return *this;
333bdd1243dSDimitry Andric   }
334bdd1243dSDimitry Andric 
335bdd1243dSDimitry Andric private:
336bdd1243dSDimitry Andric   template <class _OtherErrQual>
337bdd1243dSDimitry Andric   static constexpr bool __can_assign_from_unexpected =
338bdd1243dSDimitry Andric       _And< is_constructible<_Err, _OtherErrQual>,
339bdd1243dSDimitry Andric             is_assignable<_Err&, _OtherErrQual>,
340bdd1243dSDimitry Andric             _Lazy<_Or,
341bdd1243dSDimitry Andric                   is_nothrow_constructible<_Err, _OtherErrQual>,
342bdd1243dSDimitry Andric                   is_nothrow_move_constructible<_Tp>,
343bdd1243dSDimitry Andric                   is_nothrow_move_constructible<_Err>> >::value;
344bdd1243dSDimitry Andric 
345bdd1243dSDimitry Andric public:
346bdd1243dSDimitry Andric   template <class _OtherErr>
347bdd1243dSDimitry Andric     requires(__can_assign_from_unexpected<const _OtherErr&>)
348bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
349bdd1243dSDimitry Andric     if (__has_val_) {
350bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, __un.error());
351bdd1243dSDimitry Andric       __has_val_ = false;
352bdd1243dSDimitry Andric     } else {
353bdd1243dSDimitry Andric       __union_.__unex_ = __un.error();
354bdd1243dSDimitry Andric     }
355bdd1243dSDimitry Andric     return *this;
356bdd1243dSDimitry Andric   }
357bdd1243dSDimitry Andric 
358bdd1243dSDimitry Andric   template <class _OtherErr>
359bdd1243dSDimitry Andric     requires(__can_assign_from_unexpected<_OtherErr>)
360bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
361bdd1243dSDimitry Andric     if (__has_val_) {
362bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error()));
363bdd1243dSDimitry Andric       __has_val_ = false;
364bdd1243dSDimitry Andric     } else {
365bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__un.error());
366bdd1243dSDimitry Andric     }
367bdd1243dSDimitry Andric     return *this;
368bdd1243dSDimitry Andric   }
369bdd1243dSDimitry Andric 
370bdd1243dSDimitry Andric   template <class... _Args>
371bdd1243dSDimitry Andric     requires is_nothrow_constructible_v<_Tp, _Args...>
372bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
373bdd1243dSDimitry Andric     if (__has_val_) {
374bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
375bdd1243dSDimitry Andric     } else {
376bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
377bdd1243dSDimitry Andric     }
378b121cb00SDimitry Andric     std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
379b121cb00SDimitry Andric     __has_val_ = true;
380b121cb00SDimitry Andric     return __union_.__val_;
381bdd1243dSDimitry Andric   }
382bdd1243dSDimitry Andric 
383bdd1243dSDimitry Andric   template <class _Up, class... _Args>
384bdd1243dSDimitry Andric     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
385bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
386bdd1243dSDimitry Andric     if (__has_val_) {
387bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
388bdd1243dSDimitry Andric     } else {
389bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
390bdd1243dSDimitry Andric     }
391b121cb00SDimitry Andric     std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
392b121cb00SDimitry Andric     __has_val_ = true;
393b121cb00SDimitry Andric     return __union_.__val_;
394bdd1243dSDimitry Andric   }
395bdd1243dSDimitry Andric 
396bdd1243dSDimitry Andric public:
397bdd1243dSDimitry Andric   // [expected.object.swap], swap
398*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void
399*cb14a3feSDimitry Andric   swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp> &&
400*cb14a3feSDimitry Andric                                  is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)
401*cb14a3feSDimitry Andric     requires(is_swappable_v<_Tp> && is_swappable_v<_Err> && is_move_constructible_v<_Tp> &&
402bdd1243dSDimitry Andric              is_move_constructible_v<_Err> &&
403*cb14a3feSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> || is_nothrow_move_constructible_v<_Err>))
404bdd1243dSDimitry Andric   {
405bdd1243dSDimitry Andric     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
406bdd1243dSDimitry Andric       if constexpr (is_nothrow_move_constructible_v<_Err>) {
407bdd1243dSDimitry Andric         _Err __tmp(std::move(__with_err.__union_.__unex_));
408bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_err.__union_.__unex_));
4091ac55f4cSDimitry Andric         auto __trans = std::__make_exception_guard([&] {
410bdd1243dSDimitry Andric           std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
411bdd1243dSDimitry Andric         });
412bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
413bdd1243dSDimitry Andric         __trans.__complete();
414bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_val.__union_.__val_));
415bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp));
416bdd1243dSDimitry Andric       } else {
417bdd1243dSDimitry Andric         static_assert(is_nothrow_move_constructible_v<_Tp>,
418bdd1243dSDimitry Andric                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
419bdd1243dSDimitry Andric                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
420bdd1243dSDimitry Andric         _Tp __tmp(std::move(__with_val.__union_.__val_));
421bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_val.__union_.__val_));
4221ac55f4cSDimitry Andric         auto __trans = std::__make_exception_guard([&] {
423bdd1243dSDimitry Andric           std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp));
424bdd1243dSDimitry Andric         });
425bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
426bdd1243dSDimitry Andric         __trans.__complete();
427bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_err.__union_.__unex_));
428bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp));
429bdd1243dSDimitry Andric       }
430bdd1243dSDimitry Andric       __with_val.__has_val_ = false;
431bdd1243dSDimitry Andric       __with_err.__has_val_ = true;
432bdd1243dSDimitry Andric     };
433bdd1243dSDimitry Andric 
434bdd1243dSDimitry Andric     if (__has_val_) {
435bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
436bdd1243dSDimitry Andric         using std::swap;
437bdd1243dSDimitry Andric         swap(__union_.__val_, __rhs.__union_.__val_);
438bdd1243dSDimitry Andric       } else {
439bdd1243dSDimitry Andric         __swap_val_unex_impl(*this, __rhs);
440bdd1243dSDimitry Andric       }
441bdd1243dSDimitry Andric     } else {
442bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
443bdd1243dSDimitry Andric         __swap_val_unex_impl(__rhs, *this);
444bdd1243dSDimitry Andric       } else {
445bdd1243dSDimitry Andric         using std::swap;
446bdd1243dSDimitry Andric         swap(__union_.__unex_, __rhs.__union_.__unex_);
447bdd1243dSDimitry Andric       }
448bdd1243dSDimitry Andric     }
449bdd1243dSDimitry Andric   }
450bdd1243dSDimitry Andric 
451*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y)))
452bdd1243dSDimitry Andric     requires requires { __x.swap(__y); }
453bdd1243dSDimitry Andric   {
454bdd1243dSDimitry Andric     __x.swap(__y);
455bdd1243dSDimitry Andric   }
456bdd1243dSDimitry Andric 
457bdd1243dSDimitry Andric   // [expected.object.obs], observers
458bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
45906c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value");
460bdd1243dSDimitry Andric     return std::addressof(__union_.__val_);
461bdd1243dSDimitry Andric   }
462bdd1243dSDimitry Andric 
463bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
46406c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value");
465bdd1243dSDimitry Andric     return std::addressof(__union_.__val_);
466bdd1243dSDimitry Andric   }
467bdd1243dSDimitry Andric 
468bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
46906c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
470bdd1243dSDimitry Andric     return __union_.__val_;
471bdd1243dSDimitry Andric   }
472bdd1243dSDimitry Andric 
473bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
47406c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
475bdd1243dSDimitry Andric     return __union_.__val_;
476bdd1243dSDimitry Andric   }
477bdd1243dSDimitry Andric 
478bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
47906c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
480bdd1243dSDimitry Andric     return std::move(__union_.__val_);
481bdd1243dSDimitry Andric   }
482bdd1243dSDimitry Andric 
483bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
48406c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
485bdd1243dSDimitry Andric     return std::move(__union_.__val_);
486bdd1243dSDimitry Andric   }
487bdd1243dSDimitry Andric 
488bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
489bdd1243dSDimitry Andric 
490bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
491bdd1243dSDimitry Andric 
492bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
49306c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
494bdd1243dSDimitry Andric     if (!__has_val_) {
49506c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
496bdd1243dSDimitry Andric     }
497bdd1243dSDimitry Andric     return __union_.__val_;
498bdd1243dSDimitry Andric   }
499bdd1243dSDimitry Andric 
500bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
50106c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
502bdd1243dSDimitry Andric     if (!__has_val_) {
50306c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
504bdd1243dSDimitry Andric     }
505bdd1243dSDimitry Andric     return __union_.__val_;
506bdd1243dSDimitry Andric   }
507bdd1243dSDimitry Andric 
508bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
50906c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
51006c3fb27SDimitry Andric                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
511bdd1243dSDimitry Andric     if (!__has_val_) {
51206c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(std::move(error()));
513bdd1243dSDimitry Andric     }
514bdd1243dSDimitry Andric     return std::move(__union_.__val_);
515bdd1243dSDimitry Andric   }
516bdd1243dSDimitry Andric 
517bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
51806c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
51906c3fb27SDimitry Andric                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
520bdd1243dSDimitry Andric     if (!__has_val_) {
52106c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(std::move(error()));
522bdd1243dSDimitry Andric     }
523bdd1243dSDimitry Andric     return std::move(__union_.__val_);
524bdd1243dSDimitry Andric   }
525bdd1243dSDimitry Andric 
526bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
52706c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
528bdd1243dSDimitry Andric     return __union_.__unex_;
529bdd1243dSDimitry Andric   }
530bdd1243dSDimitry Andric 
531bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
53206c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
533bdd1243dSDimitry Andric     return __union_.__unex_;
534bdd1243dSDimitry Andric   }
535bdd1243dSDimitry Andric 
536bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
53706c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
538bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
539bdd1243dSDimitry Andric   }
540bdd1243dSDimitry Andric 
541bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
54206c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
543bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
544bdd1243dSDimitry Andric   }
545bdd1243dSDimitry Andric 
546bdd1243dSDimitry Andric   template <class _Up>
547bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
548bdd1243dSDimitry Andric     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
549bdd1243dSDimitry Andric     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
550bdd1243dSDimitry Andric     return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
551bdd1243dSDimitry Andric   }
552bdd1243dSDimitry Andric 
553bdd1243dSDimitry Andric   template <class _Up>
554bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
555bdd1243dSDimitry Andric     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
556bdd1243dSDimitry Andric     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
557bdd1243dSDimitry Andric     return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
558bdd1243dSDimitry Andric   }
559bdd1243dSDimitry Andric 
56006c3fb27SDimitry Andric   template <class _Up = _Err>
56106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& {
56206c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
56306c3fb27SDimitry Andric     static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type");
56406c3fb27SDimitry Andric     if (has_value())
56506c3fb27SDimitry Andric       return std::forward<_Up>(__error);
56606c3fb27SDimitry Andric     return error();
56706c3fb27SDimitry Andric   }
56806c3fb27SDimitry Andric 
56906c3fb27SDimitry Andric   template <class _Up = _Err>
57006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && {
57106c3fb27SDimitry Andric     static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible");
57206c3fb27SDimitry Andric     static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type");
57306c3fb27SDimitry Andric     if (has_value())
57406c3fb27SDimitry Andric       return std::forward<_Up>(__error);
57506c3fb27SDimitry Andric     return std::move(error());
57606c3fb27SDimitry Andric   }
57706c3fb27SDimitry Andric 
57806c3fb27SDimitry Andric   // [expected.void.monadic], monadic
57906c3fb27SDimitry Andric   template <class _Func>
58006c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&>
58106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
58206c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
5835f757f3fSDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
58406c3fb27SDimitry Andric     static_assert(is_same_v<typename _Up::error_type, _Err>,
5855f757f3fSDimitry Andric                   "The result of f(**this) must have the same error_type as this expected");
58606c3fb27SDimitry Andric     if (has_value()) {
5875f757f3fSDimitry Andric       return std::invoke(std::forward<_Func>(__f), __union_.__val_);
58806c3fb27SDimitry Andric     }
58906c3fb27SDimitry Andric     return _Up(unexpect, error());
59006c3fb27SDimitry Andric   }
59106c3fb27SDimitry Andric 
59206c3fb27SDimitry Andric   template <class _Func>
59306c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&>
59406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
59506c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>;
5965f757f3fSDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
59706c3fb27SDimitry Andric     static_assert(is_same_v<typename _Up::error_type, _Err>,
5985f757f3fSDimitry Andric                   "The result of f(**this) must have the same error_type as this expected");
59906c3fb27SDimitry Andric     if (has_value()) {
6005f757f3fSDimitry Andric       return std::invoke(std::forward<_Func>(__f), __union_.__val_);
60106c3fb27SDimitry Andric     }
60206c3fb27SDimitry Andric     return _Up(unexpect, error());
60306c3fb27SDimitry Andric   }
60406c3fb27SDimitry Andric 
60506c3fb27SDimitry Andric   template <class _Func>
60606c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&&>
60706c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
60806c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>;
60906c3fb27SDimitry Andric     static_assert(
6105f757f3fSDimitry Andric         __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
61106c3fb27SDimitry Andric     static_assert(is_same_v<typename _Up::error_type, _Err>,
6125f757f3fSDimitry Andric                   "The result of f(std::move(**this)) must have the same error_type as this expected");
61306c3fb27SDimitry Andric     if (has_value()) {
6145f757f3fSDimitry Andric       return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
61506c3fb27SDimitry Andric     }
61606c3fb27SDimitry Andric     return _Up(unexpect, std::move(error()));
61706c3fb27SDimitry Andric   }
61806c3fb27SDimitry Andric 
61906c3fb27SDimitry Andric   template <class _Func>
62006c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&&>
62106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
62206c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>;
62306c3fb27SDimitry Andric     static_assert(
6245f757f3fSDimitry Andric         __is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
62506c3fb27SDimitry Andric     static_assert(is_same_v<typename _Up::error_type, _Err>,
6265f757f3fSDimitry Andric                   "The result of f(std::move(**this)) must have the same error_type as this expected");
62706c3fb27SDimitry Andric     if (has_value()) {
6285f757f3fSDimitry Andric       return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
62906c3fb27SDimitry Andric     }
63006c3fb27SDimitry Andric     return _Up(unexpect, std::move(error()));
63106c3fb27SDimitry Andric   }
63206c3fb27SDimitry Andric 
63306c3fb27SDimitry Andric   template <class _Func>
63406c3fb27SDimitry Andric     requires is_constructible_v<_Tp, _Tp&>
63506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & {
63606c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>;
63706c3fb27SDimitry Andric     static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
63806c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
63906c3fb27SDimitry Andric                   "The result of f(error()) must have the same value_type as this expected");
64006c3fb27SDimitry Andric     if (has_value()) {
6415f757f3fSDimitry Andric       return _Gp(in_place, __union_.__val_);
64206c3fb27SDimitry Andric     }
64306c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), error());
64406c3fb27SDimitry Andric   }
64506c3fb27SDimitry Andric 
64606c3fb27SDimitry Andric   template <class _Func>
64706c3fb27SDimitry Andric     requires is_constructible_v<_Tp, const _Tp&>
64806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& {
64906c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>;
65006c3fb27SDimitry Andric     static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
65106c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
65206c3fb27SDimitry Andric                   "The result of f(error()) must have the same value_type as this expected");
65306c3fb27SDimitry Andric     if (has_value()) {
6545f757f3fSDimitry Andric       return _Gp(in_place, __union_.__val_);
65506c3fb27SDimitry Andric     }
65606c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), error());
65706c3fb27SDimitry Andric   }
65806c3fb27SDimitry Andric 
65906c3fb27SDimitry Andric   template <class _Func>
66006c3fb27SDimitry Andric     requires is_constructible_v<_Tp, _Tp&&>
66106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && {
66206c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>;
66306c3fb27SDimitry Andric     static_assert(
66406c3fb27SDimitry Andric         __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected");
66506c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
66606c3fb27SDimitry Andric                   "The result of f(std::move(error())) must have the same value_type as this expected");
66706c3fb27SDimitry Andric     if (has_value()) {
6685f757f3fSDimitry Andric       return _Gp(in_place, std::move(__union_.__val_));
66906c3fb27SDimitry Andric     }
67006c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), std::move(error()));
67106c3fb27SDimitry Andric   }
67206c3fb27SDimitry Andric 
67306c3fb27SDimitry Andric   template <class _Func>
67406c3fb27SDimitry Andric     requires is_constructible_v<_Tp, const _Tp&&>
67506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& {
67606c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>;
67706c3fb27SDimitry Andric     static_assert(
67806c3fb27SDimitry Andric         __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected");
67906c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
68006c3fb27SDimitry Andric                   "The result of f(std::move(error())) must have the same value_type as this expected");
68106c3fb27SDimitry Andric     if (has_value()) {
6825f757f3fSDimitry Andric       return _Gp(in_place, std::move(__union_.__val_));
68306c3fb27SDimitry Andric     }
68406c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), std::move(error()));
68506c3fb27SDimitry Andric   }
68606c3fb27SDimitry Andric 
68706c3fb27SDimitry Andric   template <class _Func>
68806c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&>
68906c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
69006c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
69106c3fb27SDimitry Andric     if (!has_value()) {
69206c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, error());
69306c3fb27SDimitry Andric     }
69406c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
695*cb14a3feSDimitry Andric       return expected<_Up, _Err>(
696*cb14a3feSDimitry Andric           __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_);
69706c3fb27SDimitry Andric     } else {
6985f757f3fSDimitry Andric       std::invoke(std::forward<_Func>(__f), __union_.__val_);
69906c3fb27SDimitry Andric       return expected<_Up, _Err>();
70006c3fb27SDimitry Andric     }
70106c3fb27SDimitry Andric   }
70206c3fb27SDimitry Andric 
70306c3fb27SDimitry Andric   template <class _Func>
70406c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&>
70506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
70606c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
70706c3fb27SDimitry Andric     if (!has_value()) {
70806c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, error());
70906c3fb27SDimitry Andric     }
71006c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
711*cb14a3feSDimitry Andric       return expected<_Up, _Err>(
712*cb14a3feSDimitry Andric           __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_);
71306c3fb27SDimitry Andric     } else {
7145f757f3fSDimitry Andric       std::invoke(std::forward<_Func>(__f), __union_.__val_);
71506c3fb27SDimitry Andric       return expected<_Up, _Err>();
71606c3fb27SDimitry Andric     }
71706c3fb27SDimitry Andric   }
71806c3fb27SDimitry Andric 
71906c3fb27SDimitry Andric   template <class _Func>
72006c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&&>
72106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
72206c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
72306c3fb27SDimitry Andric     if (!has_value()) {
72406c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, std::move(error()));
72506c3fb27SDimitry Andric     }
72606c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
72706c3fb27SDimitry Andric       return expected<_Up, _Err>(
7285f757f3fSDimitry Andric           __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_));
72906c3fb27SDimitry Andric     } else {
7305f757f3fSDimitry Andric       std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
73106c3fb27SDimitry Andric       return expected<_Up, _Err>();
73206c3fb27SDimitry Andric     }
73306c3fb27SDimitry Andric   }
73406c3fb27SDimitry Andric 
73506c3fb27SDimitry Andric   template <class _Func>
73606c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&&>
73706c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
73806c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
73906c3fb27SDimitry Andric     if (!has_value()) {
74006c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, std::move(error()));
74106c3fb27SDimitry Andric     }
74206c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
74306c3fb27SDimitry Andric       return expected<_Up, _Err>(
7445f757f3fSDimitry Andric           __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_));
74506c3fb27SDimitry Andric     } else {
7465f757f3fSDimitry Andric       std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
74706c3fb27SDimitry Andric       return expected<_Up, _Err>();
74806c3fb27SDimitry Andric     }
74906c3fb27SDimitry Andric   }
75006c3fb27SDimitry Andric 
75106c3fb27SDimitry Andric   template <class _Func>
75206c3fb27SDimitry Andric     requires is_constructible_v<_Tp, _Tp&>
75306c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & {
75406c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>;
75506c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
75606c3fb27SDimitry Andric                   "The result of f(error()) must be a valid template argument for unexpected");
75706c3fb27SDimitry Andric     if (has_value()) {
7585f757f3fSDimitry Andric       return expected<_Tp, _Gp>(in_place, __union_.__val_);
75906c3fb27SDimitry Andric     }
76006c3fb27SDimitry Andric     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
76106c3fb27SDimitry Andric   }
76206c3fb27SDimitry Andric 
76306c3fb27SDimitry Andric   template <class _Func>
76406c3fb27SDimitry Andric     requires is_constructible_v<_Tp, const _Tp&>
76506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& {
76606c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>;
76706c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
76806c3fb27SDimitry Andric                   "The result of f(error()) must be a valid template argument for unexpected");
76906c3fb27SDimitry Andric     if (has_value()) {
7705f757f3fSDimitry Andric       return expected<_Tp, _Gp>(in_place, __union_.__val_);
77106c3fb27SDimitry Andric     }
77206c3fb27SDimitry Andric     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
77306c3fb27SDimitry Andric   }
77406c3fb27SDimitry Andric 
77506c3fb27SDimitry Andric   template <class _Func>
77606c3fb27SDimitry Andric     requires is_constructible_v<_Tp, _Tp&&>
77706c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && {
77806c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>;
77906c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
78006c3fb27SDimitry Andric                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
78106c3fb27SDimitry Andric     if (has_value()) {
7825f757f3fSDimitry Andric       return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_));
78306c3fb27SDimitry Andric     }
78406c3fb27SDimitry Andric     return expected<_Tp, _Gp>(
78506c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
78606c3fb27SDimitry Andric   }
78706c3fb27SDimitry Andric 
78806c3fb27SDimitry Andric   template <class _Func>
78906c3fb27SDimitry Andric     requires is_constructible_v<_Tp, const _Tp&&>
79006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& {
79106c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>;
79206c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
79306c3fb27SDimitry Andric                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
79406c3fb27SDimitry Andric     if (has_value()) {
7955f757f3fSDimitry Andric       return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_));
79606c3fb27SDimitry Andric     }
79706c3fb27SDimitry Andric     return expected<_Tp, _Gp>(
79806c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
79906c3fb27SDimitry Andric   }
80006c3fb27SDimitry Andric 
801bdd1243dSDimitry Andric   // [expected.object.eq], equality operators
802bdd1243dSDimitry Andric   template <class _T2, class _E2>
803bdd1243dSDimitry Andric     requires(!is_void_v<_T2>)
804bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
805bdd1243dSDimitry Andric     if (__x.__has_val_ != __y.__has_val_) {
806bdd1243dSDimitry Andric       return false;
807bdd1243dSDimitry Andric     } else {
808bdd1243dSDimitry Andric       if (__x.__has_val_) {
809bdd1243dSDimitry Andric         return __x.__union_.__val_ == __y.__union_.__val_;
810bdd1243dSDimitry Andric       } else {
811bdd1243dSDimitry Andric         return __x.__union_.__unex_ == __y.__union_.__unex_;
812bdd1243dSDimitry Andric       }
813bdd1243dSDimitry Andric     }
814bdd1243dSDimitry Andric   }
815bdd1243dSDimitry Andric 
816bdd1243dSDimitry Andric   template <class _T2>
817bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
818bdd1243dSDimitry Andric     return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
819bdd1243dSDimitry Andric   }
820bdd1243dSDimitry Andric 
821bdd1243dSDimitry Andric   template <class _E2>
822bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
823bdd1243dSDimitry Andric     return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
824bdd1243dSDimitry Andric   }
825bdd1243dSDimitry Andric 
826bdd1243dSDimitry Andric private:
82706c3fb27SDimitry Andric   template <class _ValueType, class _ErrorType>
82806c3fb27SDimitry Andric   union __union_t {
829b121cb00SDimitry Andric     template <class... _Args>
830b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
831b121cb00SDimitry Andric         : __val_(std::forward<_Args>(__args)...) {}
832b121cb00SDimitry Andric 
833b121cb00SDimitry Andric     template <class... _Args>
834b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
835b121cb00SDimitry Andric         : __unex_(std::forward<_Args>(__args)...) {}
83606c3fb27SDimitry Andric 
83706c3fb27SDimitry Andric     template <class _Func, class... _Args>
83806c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
83906c3fb27SDimitry Andric         std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
84006c3fb27SDimitry Andric         : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
84106c3fb27SDimitry Andric 
84206c3fb27SDimitry Andric     template <class _Func, class... _Args>
84306c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
84406c3fb27SDimitry Andric         std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
84506c3fb27SDimitry Andric         : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
846bdd1243dSDimitry Andric 
847b121cb00SDimitry Andric     template <class _Union>
848b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
849b121cb00SDimitry Andric       if (__has_val)
850b121cb00SDimitry Andric         std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
851b121cb00SDimitry Andric       else
852b121cb00SDimitry Andric         std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
853b121cb00SDimitry Andric     }
854b121cb00SDimitry Andric 
855bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
85606c3fb27SDimitry Andric       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
85706c3fb27SDimitry Andric     = default;
85806c3fb27SDimitry Andric 
85906c3fb27SDimitry Andric     // the expected's destructor handles this
86006c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
86106c3fb27SDimitry Andric 
86206c3fb27SDimitry Andric     _ValueType __val_;
86306c3fb27SDimitry Andric     _ErrorType __unex_;
86406c3fb27SDimitry Andric   };
86506c3fb27SDimitry Andric 
86606c3fb27SDimitry Andric   // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
86706c3fb27SDimitry Andric   // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
86806c3fb27SDimitry Andric   // it's not clear that it's implementable, given that the function is allowed to clobber
86906c3fb27SDimitry Andric   // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
87006c3fb27SDimitry Andric   template <class _ValueType, class _ErrorType>
87106c3fb27SDimitry Andric     requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
87206c3fb27SDimitry Andric   union __union_t<_ValueType, _ErrorType> {
873b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&)            = default;
874b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
875b121cb00SDimitry Andric 
876b121cb00SDimitry Andric     template <class... _Args>
877b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
878b121cb00SDimitry Andric         : __val_(std::forward<_Args>(__args)...) {}
879b121cb00SDimitry Andric 
880b121cb00SDimitry Andric     template <class... _Args>
881b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
882b121cb00SDimitry Andric         : __unex_(std::forward<_Args>(__args)...) {}
88306c3fb27SDimitry Andric 
88406c3fb27SDimitry Andric     template <class _Func, class... _Args>
88506c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
88606c3fb27SDimitry Andric         std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
88706c3fb27SDimitry Andric         : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
88806c3fb27SDimitry Andric 
88906c3fb27SDimitry Andric     template <class _Func, class... _Args>
89006c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
89106c3fb27SDimitry Andric         std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
89206c3fb27SDimitry Andric         : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
89306c3fb27SDimitry Andric 
894b121cb00SDimitry Andric     template <class _Union>
895b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
896b121cb00SDimitry Andric       if (__has_val)
897b121cb00SDimitry Andric         std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
898b121cb00SDimitry Andric       else
899b121cb00SDimitry Andric         std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
900b121cb00SDimitry Andric     }
901b121cb00SDimitry Andric 
90206c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
90306c3fb27SDimitry Andric       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
904bdd1243dSDimitry Andric     = default;
905bdd1243dSDimitry Andric 
906bdd1243dSDimitry Andric     // the expected's destructor handles this
907bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
90806c3fb27SDimitry Andric       requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
909bdd1243dSDimitry Andric     {}
910bdd1243dSDimitry Andric 
91106c3fb27SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
91206c3fb27SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
91306c3fb27SDimitry Andric   };
914bdd1243dSDimitry Andric 
91506c3fb27SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
916bdd1243dSDimitry Andric   bool __has_val_;
917bdd1243dSDimitry Andric };
918bdd1243dSDimitry Andric 
919bdd1243dSDimitry Andric template <class _Tp, class _Err>
920bdd1243dSDimitry Andric   requires is_void_v<_Tp>
921bdd1243dSDimitry Andric class expected<_Tp, _Err> {
922bdd1243dSDimitry Andric   static_assert(__valid_std_unexpected<_Err>::value,
923bdd1243dSDimitry Andric                 "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
924bdd1243dSDimitry Andric                 "valid argument for unexpected<E> is ill-formed");
925bdd1243dSDimitry Andric 
926bdd1243dSDimitry Andric   template <class, class>
927bdd1243dSDimitry Andric   friend class expected;
928bdd1243dSDimitry Andric 
929bdd1243dSDimitry Andric   template <class _Up, class _OtherErr, class _OtherErrQual>
930bdd1243dSDimitry Andric   using __can_convert =
931bdd1243dSDimitry Andric       _And< is_void<_Up>,
932bdd1243dSDimitry Andric             is_constructible<_Err, _OtherErrQual>,
933bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
934bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
935bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
936bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
937bdd1243dSDimitry Andric 
938bdd1243dSDimitry Andric public:
939bdd1243dSDimitry Andric   using value_type      = _Tp;
940bdd1243dSDimitry Andric   using error_type      = _Err;
941bdd1243dSDimitry Andric   using unexpected_type = unexpected<_Err>;
942bdd1243dSDimitry Andric 
943bdd1243dSDimitry Andric   template <class _Up>
944bdd1243dSDimitry Andric   using rebind = expected<_Up, error_type>;
945bdd1243dSDimitry Andric 
946bdd1243dSDimitry Andric   // [expected.void.ctor], constructors
947bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {}
948bdd1243dSDimitry Andric 
949bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
950bdd1243dSDimitry Andric 
951bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
952bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
953bdd1243dSDimitry Andric   = default;
954bdd1243dSDimitry Andric 
955*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs) noexcept(
956*cb14a3feSDimitry Andric       is_nothrow_copy_constructible_v<_Err>) // strengthened
957bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
958b121cb00SDimitry Andric       : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
959bdd1243dSDimitry Andric 
960bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
961bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
962bdd1243dSDimitry Andric   = default;
963bdd1243dSDimitry Andric 
964*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs) noexcept(is_nothrow_move_constructible_v<_Err>)
965bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
966b121cb00SDimitry Andric       : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
967bdd1243dSDimitry Andric 
968bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
969bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
970bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
971*cb14a3feSDimitry Andric       expected(const expected<_Up, _OtherErr>& __rhs) noexcept(
972*cb14a3feSDimitry Andric           is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
973b121cb00SDimitry Andric       : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
974bdd1243dSDimitry Andric 
975bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
976bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
977bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
978*cb14a3feSDimitry Andric       expected(expected<_Up, _OtherErr>&& __rhs) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
979b121cb00SDimitry Andric       : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
980bdd1243dSDimitry Andric 
981bdd1243dSDimitry Andric   template <class _OtherErr>
982bdd1243dSDimitry Andric     requires is_constructible_v<_Err, const _OtherErr&>
983*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>) expected(
984*cb14a3feSDimitry Andric       const unexpected<_OtherErr>& __unex) noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
985b121cb00SDimitry Andric       : __union_(std::unexpect, __unex.error()), __has_val_(false) {}
986bdd1243dSDimitry Andric 
987bdd1243dSDimitry Andric   template <class _OtherErr>
988bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _OtherErr>
989bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
990*cb14a3feSDimitry Andric       expected(unexpected<_OtherErr>&& __unex) noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
991b121cb00SDimitry Andric       : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
992bdd1243dSDimitry Andric 
993bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
994bdd1243dSDimitry Andric 
995bdd1243dSDimitry Andric   template <class... _Args>
996bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _Args...>
997*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args) noexcept(
998*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Err, _Args...>) // strengthened
999b121cb00SDimitry Andric       : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
1000bdd1243dSDimitry Andric 
1001bdd1243dSDimitry Andric   template <class _Up, class... _Args>
1002bdd1243dSDimitry Andric     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
1003*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args) noexcept(
1004*cb14a3feSDimitry Andric       is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
1005b121cb00SDimitry Andric       : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
1006bdd1243dSDimitry Andric 
100706c3fb27SDimitry Andric private:
100806c3fb27SDimitry Andric   template <class _Func>
100906c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f)
101006c3fb27SDimitry Andric       : __has_val_(true) {
101106c3fb27SDimitry Andric     std::invoke(std::forward<_Func>(__f));
101206c3fb27SDimitry Andric   }
101306c3fb27SDimitry Andric 
101406c3fb27SDimitry Andric   template <class _Func, class... _Args>
101506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
101606c3fb27SDimitry Andric       __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
101706c3fb27SDimitry Andric       : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {}
101806c3fb27SDimitry Andric 
101906c3fb27SDimitry Andric public:
1020bdd1243dSDimitry Andric   // [expected.void.dtor], destructor
1021bdd1243dSDimitry Andric 
1022bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
1023bdd1243dSDimitry Andric     requires is_trivially_destructible_v<_Err>
1024bdd1243dSDimitry Andric   = default;
1025bdd1243dSDimitry Andric 
1026bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
1027bdd1243dSDimitry Andric     requires(!is_trivially_destructible_v<_Err>)
1028bdd1243dSDimitry Andric   {
1029bdd1243dSDimitry Andric     if (!__has_val_) {
1030bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
1031bdd1243dSDimitry Andric     }
1032bdd1243dSDimitry Andric   }
1033bdd1243dSDimitry Andric 
1034bdd1243dSDimitry Andric   // [expected.void.assign], assignment
1035bdd1243dSDimitry Andric 
1036bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
1037bdd1243dSDimitry Andric 
1038*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs) noexcept(
1039*cb14a3feSDimitry Andric       is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
1040bdd1243dSDimitry Andric     requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
1041bdd1243dSDimitry Andric   {
1042bdd1243dSDimitry Andric     if (__has_val_) {
1043bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
1044bdd1243dSDimitry Andric         std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
1045bdd1243dSDimitry Andric         __has_val_ = false;
1046bdd1243dSDimitry Andric       }
1047bdd1243dSDimitry Andric     } else {
1048bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
1049bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__union_.__unex_));
1050bdd1243dSDimitry Andric         __has_val_ = true;
1051bdd1243dSDimitry Andric       } else {
1052bdd1243dSDimitry Andric         __union_.__unex_ = __rhs.__union_.__unex_;
1053bdd1243dSDimitry Andric       }
1054bdd1243dSDimitry Andric     }
1055bdd1243dSDimitry Andric     return *this;
1056bdd1243dSDimitry Andric   }
1057bdd1243dSDimitry Andric 
1058bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete;
1059bdd1243dSDimitry Andric 
1060*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected&
1061*cb14a3feSDimitry Andric   operator=(expected&& __rhs) noexcept(is_nothrow_move_assignable_v<_Err> && is_nothrow_move_constructible_v<_Err>)
1062*cb14a3feSDimitry Andric     requires(is_move_assignable_v<_Err> && is_move_constructible_v<_Err>)
1063bdd1243dSDimitry Andric   {
1064bdd1243dSDimitry Andric     if (__has_val_) {
1065bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
1066bdd1243dSDimitry Andric         std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
1067bdd1243dSDimitry Andric         __has_val_ = false;
1068bdd1243dSDimitry Andric       }
1069bdd1243dSDimitry Andric     } else {
1070bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
1071bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__union_.__unex_));
1072bdd1243dSDimitry Andric         __has_val_ = true;
1073bdd1243dSDimitry Andric       } else {
1074bdd1243dSDimitry Andric         __union_.__unex_ = std::move(__rhs.__union_.__unex_);
1075bdd1243dSDimitry Andric       }
1076bdd1243dSDimitry Andric     }
1077bdd1243dSDimitry Andric     return *this;
1078bdd1243dSDimitry Andric   }
1079bdd1243dSDimitry Andric 
1080bdd1243dSDimitry Andric   template <class _OtherErr>
1081bdd1243dSDimitry Andric     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
1082bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
1083bdd1243dSDimitry Andric     if (__has_val_) {
1084bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __un.error());
1085bdd1243dSDimitry Andric       __has_val_ = false;
1086bdd1243dSDimitry Andric     } else {
1087bdd1243dSDimitry Andric       __union_.__unex_ = __un.error();
1088bdd1243dSDimitry Andric     }
1089bdd1243dSDimitry Andric     return *this;
1090bdd1243dSDimitry Andric   }
1091bdd1243dSDimitry Andric 
1092bdd1243dSDimitry Andric   template <class _OtherErr>
1093bdd1243dSDimitry Andric     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
1094bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
1095bdd1243dSDimitry Andric     if (__has_val_) {
1096bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error()));
1097bdd1243dSDimitry Andric       __has_val_ = false;
1098bdd1243dSDimitry Andric     } else {
1099bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__un.error());
1100bdd1243dSDimitry Andric     }
1101bdd1243dSDimitry Andric     return *this;
1102bdd1243dSDimitry Andric   }
1103bdd1243dSDimitry Andric 
1104bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
1105bdd1243dSDimitry Andric     if (!__has_val_) {
1106bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
1107bdd1243dSDimitry Andric       __has_val_ = true;
1108bdd1243dSDimitry Andric     }
1109bdd1243dSDimitry Andric   }
1110bdd1243dSDimitry Andric 
1111bdd1243dSDimitry Andric   // [expected.void.swap], swap
1112*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void
1113*cb14a3feSDimitry Andric   swap(expected& __rhs) noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)
1114bdd1243dSDimitry Andric     requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>)
1115bdd1243dSDimitry Andric   {
1116bdd1243dSDimitry Andric     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
1117bdd1243dSDimitry Andric       std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
1118bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__with_err.__union_.__unex_));
1119bdd1243dSDimitry Andric       __with_val.__has_val_ = false;
1120bdd1243dSDimitry Andric       __with_err.__has_val_ = true;
1121bdd1243dSDimitry Andric     };
1122bdd1243dSDimitry Andric 
1123bdd1243dSDimitry Andric     if (__has_val_) {
1124bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
1125bdd1243dSDimitry Andric         __swap_val_unex_impl(*this, __rhs);
1126bdd1243dSDimitry Andric       }
1127bdd1243dSDimitry Andric     } else {
1128bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
1129bdd1243dSDimitry Andric         __swap_val_unex_impl(__rhs, *this);
1130bdd1243dSDimitry Andric       } else {
1131bdd1243dSDimitry Andric         using std::swap;
1132bdd1243dSDimitry Andric         swap(__union_.__unex_, __rhs.__union_.__unex_);
1133bdd1243dSDimitry Andric       }
1134bdd1243dSDimitry Andric     }
1135bdd1243dSDimitry Andric   }
1136bdd1243dSDimitry Andric 
1137*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y) noexcept(noexcept(__x.swap(__y)))
1138bdd1243dSDimitry Andric     requires requires { __x.swap(__y); }
1139bdd1243dSDimitry Andric   {
1140bdd1243dSDimitry Andric     __x.swap(__y);
1141bdd1243dSDimitry Andric   }
1142bdd1243dSDimitry Andric 
1143bdd1243dSDimitry Andric   // [expected.void.obs], observers
1144bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
1145bdd1243dSDimitry Andric 
1146bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
1147bdd1243dSDimitry Andric 
1148bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
114906c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
1150bdd1243dSDimitry Andric   }
1151bdd1243dSDimitry Andric 
1152bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
1153bdd1243dSDimitry Andric     if (!__has_val_) {
115406c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(__union_.__unex_);
1155bdd1243dSDimitry Andric     }
1156bdd1243dSDimitry Andric   }
1157bdd1243dSDimitry Andric 
1158bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
1159bdd1243dSDimitry Andric     if (!__has_val_) {
116006c3fb27SDimitry Andric       std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
1161bdd1243dSDimitry Andric     }
1162bdd1243dSDimitry Andric   }
1163bdd1243dSDimitry Andric 
1164bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
116506c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
1166bdd1243dSDimitry Andric     return __union_.__unex_;
1167bdd1243dSDimitry Andric   }
1168bdd1243dSDimitry Andric 
1169bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
117006c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
1171bdd1243dSDimitry Andric     return __union_.__unex_;
1172bdd1243dSDimitry Andric   }
1173bdd1243dSDimitry Andric 
1174bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
117506c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
1176bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
1177bdd1243dSDimitry Andric   }
1178bdd1243dSDimitry Andric 
1179bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
118006c3fb27SDimitry Andric     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
1181bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
1182bdd1243dSDimitry Andric   }
1183bdd1243dSDimitry Andric 
118406c3fb27SDimitry Andric   template <class _Up = _Err>
118506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& {
118606c3fb27SDimitry Andric     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
118706c3fb27SDimitry Andric     static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type");
118806c3fb27SDimitry Andric     if (has_value()) {
118906c3fb27SDimitry Andric       return std::forward<_Up>(__error);
119006c3fb27SDimitry Andric     }
119106c3fb27SDimitry Andric     return error();
119206c3fb27SDimitry Andric   }
119306c3fb27SDimitry Andric 
119406c3fb27SDimitry Andric   template <class _Up = _Err>
119506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && {
119606c3fb27SDimitry Andric     static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible");
119706c3fb27SDimitry Andric     static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type");
119806c3fb27SDimitry Andric     if (has_value()) {
119906c3fb27SDimitry Andric       return std::forward<_Up>(__error);
120006c3fb27SDimitry Andric     }
120106c3fb27SDimitry Andric     return std::move(error());
120206c3fb27SDimitry Andric   }
120306c3fb27SDimitry Andric 
120406c3fb27SDimitry Andric   // [expected.void.monadic], monadic
120506c3fb27SDimitry Andric   template <class _Func>
120606c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&>
120706c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
120806c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func>>;
120906c3fb27SDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
121006c3fb27SDimitry Andric     static_assert(
121106c3fb27SDimitry Andric         is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected");
121206c3fb27SDimitry Andric     if (has_value()) {
121306c3fb27SDimitry Andric       return std::invoke(std::forward<_Func>(__f));
121406c3fb27SDimitry Andric     }
121506c3fb27SDimitry Andric     return _Up(unexpect, error());
121606c3fb27SDimitry Andric   }
121706c3fb27SDimitry Andric 
121806c3fb27SDimitry Andric   template <class _Func>
121906c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&>
122006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
122106c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func>>;
122206c3fb27SDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
122306c3fb27SDimitry Andric     static_assert(
122406c3fb27SDimitry Andric         is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected");
122506c3fb27SDimitry Andric     if (has_value()) {
122606c3fb27SDimitry Andric       return std::invoke(std::forward<_Func>(__f));
122706c3fb27SDimitry Andric     }
122806c3fb27SDimitry Andric     return _Up(unexpect, error());
122906c3fb27SDimitry Andric   }
123006c3fb27SDimitry Andric 
123106c3fb27SDimitry Andric   template <class _Func>
123206c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&&>
123306c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
123406c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func>>;
123506c3fb27SDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
123606c3fb27SDimitry Andric     static_assert(
123706c3fb27SDimitry Andric         is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected");
123806c3fb27SDimitry Andric     if (has_value()) {
123906c3fb27SDimitry Andric       return std::invoke(std::forward<_Func>(__f));
124006c3fb27SDimitry Andric     }
124106c3fb27SDimitry Andric     return _Up(unexpect, std::move(error()));
124206c3fb27SDimitry Andric   }
124306c3fb27SDimitry Andric 
124406c3fb27SDimitry Andric   template <class _Func>
124506c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&&>
124606c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
124706c3fb27SDimitry Andric     using _Up = remove_cvref_t<invoke_result_t<_Func>>;
124806c3fb27SDimitry Andric     static_assert(__is_std_expected<_Up>::value, "The result of f() must be a specialization of std::expected");
124906c3fb27SDimitry Andric     static_assert(
125006c3fb27SDimitry Andric         is_same_v<typename _Up::error_type, _Err>, "The result of f() must have the same error_type as this expected");
125106c3fb27SDimitry Andric     if (has_value()) {
125206c3fb27SDimitry Andric       return std::invoke(std::forward<_Func>(__f));
125306c3fb27SDimitry Andric     }
125406c3fb27SDimitry Andric     return _Up(unexpect, std::move(error()));
125506c3fb27SDimitry Andric   }
125606c3fb27SDimitry Andric 
125706c3fb27SDimitry Andric   template <class _Func>
125806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & {
125906c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>;
126006c3fb27SDimitry Andric     static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
126106c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
126206c3fb27SDimitry Andric                   "The result of f(error()) must have the same value_type as this expected");
126306c3fb27SDimitry Andric     if (has_value()) {
126406c3fb27SDimitry Andric       return _Gp();
126506c3fb27SDimitry Andric     }
126606c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), error());
126706c3fb27SDimitry Andric   }
126806c3fb27SDimitry Andric 
126906c3fb27SDimitry Andric   template <class _Func>
127006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& {
127106c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>;
127206c3fb27SDimitry Andric     static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected");
127306c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
127406c3fb27SDimitry Andric                   "The result of f(error()) must have the same value_type as this expected");
127506c3fb27SDimitry Andric     if (has_value()) {
127606c3fb27SDimitry Andric       return _Gp();
127706c3fb27SDimitry Andric     }
127806c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), error());
127906c3fb27SDimitry Andric   }
128006c3fb27SDimitry Andric 
128106c3fb27SDimitry Andric   template <class _Func>
128206c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && {
128306c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>;
1284*cb14a3feSDimitry Andric     static_assert(
1285*cb14a3feSDimitry Andric         __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected");
128606c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
128706c3fb27SDimitry Andric                   "The result of f(std::move(error())) must have the same value_type as this expected");
128806c3fb27SDimitry Andric     if (has_value()) {
128906c3fb27SDimitry Andric       return _Gp();
129006c3fb27SDimitry Andric     }
129106c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), std::move(error()));
129206c3fb27SDimitry Andric   }
129306c3fb27SDimitry Andric 
129406c3fb27SDimitry Andric   template <class _Func>
129506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& {
129606c3fb27SDimitry Andric     using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>;
1297*cb14a3feSDimitry Andric     static_assert(
1298*cb14a3feSDimitry Andric         __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected");
129906c3fb27SDimitry Andric     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
130006c3fb27SDimitry Andric                   "The result of f(std::move(error())) must have the same value_type as this expected");
130106c3fb27SDimitry Andric     if (has_value()) {
130206c3fb27SDimitry Andric       return _Gp();
130306c3fb27SDimitry Andric     }
130406c3fb27SDimitry Andric     return std::invoke(std::forward<_Func>(__f), std::move(error()));
130506c3fb27SDimitry Andric   }
130606c3fb27SDimitry Andric 
130706c3fb27SDimitry Andric   template <class _Func>
130806c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&>
130906c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
131006c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func>>;
131106c3fb27SDimitry Andric     if (!has_value()) {
131206c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, error());
131306c3fb27SDimitry Andric     }
131406c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
131506c3fb27SDimitry Andric       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f));
131606c3fb27SDimitry Andric     } else {
131706c3fb27SDimitry Andric       std::invoke(std::forward<_Func>(__f));
131806c3fb27SDimitry Andric       return expected<_Up, _Err>();
131906c3fb27SDimitry Andric     }
132006c3fb27SDimitry Andric   }
132106c3fb27SDimitry Andric 
132206c3fb27SDimitry Andric   template <class _Func>
132306c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&>
132406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
132506c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func>>;
132606c3fb27SDimitry Andric     if (!has_value()) {
132706c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, error());
132806c3fb27SDimitry Andric     }
132906c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
133006c3fb27SDimitry Andric       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f));
133106c3fb27SDimitry Andric     } else {
133206c3fb27SDimitry Andric       std::invoke(std::forward<_Func>(__f));
133306c3fb27SDimitry Andric       return expected<_Up, _Err>();
133406c3fb27SDimitry Andric     }
133506c3fb27SDimitry Andric   }
133606c3fb27SDimitry Andric 
133706c3fb27SDimitry Andric   template <class _Func>
133806c3fb27SDimitry Andric     requires is_constructible_v<_Err, _Err&&>
133906c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
134006c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func>>;
134106c3fb27SDimitry Andric     if (!has_value()) {
134206c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, std::move(error()));
134306c3fb27SDimitry Andric     }
134406c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
134506c3fb27SDimitry Andric       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f));
134606c3fb27SDimitry Andric     } else {
134706c3fb27SDimitry Andric       std::invoke(std::forward<_Func>(__f));
134806c3fb27SDimitry Andric       return expected<_Up, _Err>();
134906c3fb27SDimitry Andric     }
135006c3fb27SDimitry Andric   }
135106c3fb27SDimitry Andric 
135206c3fb27SDimitry Andric   template <class _Func>
135306c3fb27SDimitry Andric     requires is_constructible_v<_Err, const _Err&&>
135406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
135506c3fb27SDimitry Andric     using _Up = remove_cv_t<invoke_result_t<_Func>>;
135606c3fb27SDimitry Andric     if (!has_value()) {
135706c3fb27SDimitry Andric       return expected<_Up, _Err>(unexpect, std::move(error()));
135806c3fb27SDimitry Andric     }
135906c3fb27SDimitry Andric     if constexpr (!is_void_v<_Up>) {
136006c3fb27SDimitry Andric       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f));
136106c3fb27SDimitry Andric     } else {
136206c3fb27SDimitry Andric       std::invoke(std::forward<_Func>(__f));
136306c3fb27SDimitry Andric       return expected<_Up, _Err>();
136406c3fb27SDimitry Andric     }
136506c3fb27SDimitry Andric   }
136606c3fb27SDimitry Andric 
136706c3fb27SDimitry Andric   template <class _Func>
136806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & {
136906c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>;
137006c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
137106c3fb27SDimitry Andric                   "The result of f(error()) must be a valid template argument for unexpected");
137206c3fb27SDimitry Andric     if (has_value()) {
137306c3fb27SDimitry Andric       return expected<_Tp, _Gp>();
137406c3fb27SDimitry Andric     }
137506c3fb27SDimitry Andric     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
137606c3fb27SDimitry Andric   }
137706c3fb27SDimitry Andric 
137806c3fb27SDimitry Andric   template <class _Func>
137906c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& {
138006c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>;
138106c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
138206c3fb27SDimitry Andric                   "The result of f(error()) must be a valid template argument for unexpected");
138306c3fb27SDimitry Andric     if (has_value()) {
138406c3fb27SDimitry Andric       return expected<_Tp, _Gp>();
138506c3fb27SDimitry Andric     }
138606c3fb27SDimitry Andric     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
138706c3fb27SDimitry Andric   }
138806c3fb27SDimitry Andric 
138906c3fb27SDimitry Andric   template <class _Func>
139006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && {
139106c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>;
139206c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
139306c3fb27SDimitry Andric                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
139406c3fb27SDimitry Andric     if (has_value()) {
139506c3fb27SDimitry Andric       return expected<_Tp, _Gp>();
139606c3fb27SDimitry Andric     }
139706c3fb27SDimitry Andric     return expected<_Tp, _Gp>(
139806c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
139906c3fb27SDimitry Andric   }
140006c3fb27SDimitry Andric 
140106c3fb27SDimitry Andric   template <class _Func>
140206c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& {
140306c3fb27SDimitry Andric     using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>;
140406c3fb27SDimitry Andric     static_assert(__valid_std_unexpected<_Gp>::value,
140506c3fb27SDimitry Andric                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
140606c3fb27SDimitry Andric     if (has_value()) {
140706c3fb27SDimitry Andric       return expected<_Tp, _Gp>();
140806c3fb27SDimitry Andric     }
140906c3fb27SDimitry Andric     return expected<_Tp, _Gp>(
141006c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
141106c3fb27SDimitry Andric   }
141206c3fb27SDimitry Andric 
1413bdd1243dSDimitry Andric   // [expected.void.eq], equality operators
1414bdd1243dSDimitry Andric   template <class _T2, class _E2>
1415bdd1243dSDimitry Andric     requires is_void_v<_T2>
1416bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
1417bdd1243dSDimitry Andric     if (__x.__has_val_ != __y.__has_val_) {
1418bdd1243dSDimitry Andric       return false;
1419bdd1243dSDimitry Andric     } else {
1420bdd1243dSDimitry Andric       return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
1421bdd1243dSDimitry Andric     }
1422bdd1243dSDimitry Andric   }
1423bdd1243dSDimitry Andric 
1424bdd1243dSDimitry Andric   template <class _E2>
1425bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
1426bdd1243dSDimitry Andric     return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
1427bdd1243dSDimitry Andric   }
1428bdd1243dSDimitry Andric 
1429bdd1243dSDimitry Andric private:
1430bdd1243dSDimitry Andric   struct __empty_t {};
143106c3fb27SDimitry Andric 
143206c3fb27SDimitry Andric   template <class _ErrorType>
143306c3fb27SDimitry Andric   union __union_t {
1434bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
1435bdd1243dSDimitry Andric 
1436b121cb00SDimitry Andric     template <class... _Args>
1437b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
1438b121cb00SDimitry Andric         : __unex_(std::forward<_Args>(__args)...) {}
1439b121cb00SDimitry Andric 
144006c3fb27SDimitry Andric     template <class _Func, class... _Args>
144106c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
144206c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
144306c3fb27SDimitry Andric         : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
144406c3fb27SDimitry Andric 
1445b121cb00SDimitry Andric     template <class _Union>
1446b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
1447b121cb00SDimitry Andric       if (__has_val)
1448b121cb00SDimitry Andric         std::construct_at(std::addressof(__empty_));
1449b121cb00SDimitry Andric       else
1450b121cb00SDimitry Andric         std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
1451b121cb00SDimitry Andric     }
1452b121cb00SDimitry Andric 
1453bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
145406c3fb27SDimitry Andric       requires(is_trivially_destructible_v<_ErrorType>)
145506c3fb27SDimitry Andric     = default;
145606c3fb27SDimitry Andric 
145706c3fb27SDimitry Andric     // the expected's destructor handles this
145806c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
145906c3fb27SDimitry Andric 
146006c3fb27SDimitry Andric     __empty_t __empty_;
146106c3fb27SDimitry Andric     _ErrorType __unex_;
146206c3fb27SDimitry Andric   };
146306c3fb27SDimitry Andric 
146406c3fb27SDimitry Andric   // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
146506c3fb27SDimitry Andric   // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
146606c3fb27SDimitry Andric   // it's not clear that it's implementable, given that the function is allowed to clobber
146706c3fb27SDimitry Andric   // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
146806c3fb27SDimitry Andric   template <class _ErrorType>
146906c3fb27SDimitry Andric     requires is_trivially_move_constructible_v<_ErrorType>
147006c3fb27SDimitry Andric   union __union_t<_ErrorType> {
147106c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
14725f757f3fSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&)            = default;
14735f757f3fSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
147406c3fb27SDimitry Andric 
1475b121cb00SDimitry Andric     template <class... _Args>
1476b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
1477b121cb00SDimitry Andric         : __unex_(std::forward<_Args>(__args)...) {}
1478b121cb00SDimitry Andric 
147906c3fb27SDimitry Andric     template <class _Func, class... _Args>
148006c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
148106c3fb27SDimitry Andric         __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
148206c3fb27SDimitry Andric         : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
148306c3fb27SDimitry Andric 
1484b121cb00SDimitry Andric     template <class _Union>
1485b121cb00SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
1486b121cb00SDimitry Andric       if (__has_val)
1487b121cb00SDimitry Andric         std::construct_at(std::addressof(__empty_));
1488b121cb00SDimitry Andric       else
1489b121cb00SDimitry Andric         std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
1490b121cb00SDimitry Andric     }
1491b121cb00SDimitry Andric 
149206c3fb27SDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
149306c3fb27SDimitry Andric       requires(is_trivially_destructible_v<_ErrorType>)
1494bdd1243dSDimitry Andric     = default;
1495bdd1243dSDimitry Andric 
1496bdd1243dSDimitry Andric     // the expected's destructor handles this
1497bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
149806c3fb27SDimitry Andric       requires(!is_trivially_destructible_v<_ErrorType>)
1499bdd1243dSDimitry Andric     {}
1500bdd1243dSDimitry Andric 
1501bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
150206c3fb27SDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
150306c3fb27SDimitry Andric   };
1504bdd1243dSDimitry Andric 
150506c3fb27SDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
1506bdd1243dSDimitry Andric   bool __has_val_;
1507bdd1243dSDimitry Andric };
1508bdd1243dSDimitry Andric 
1509bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD
1510bdd1243dSDimitry Andric 
1511bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23
1512bdd1243dSDimitry Andric 
151306c3fb27SDimitry Andric _LIBCPP_POP_MACROS
151406c3fb27SDimitry Andric 
1515bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H
1516