xref: /freebsd-src/contrib/llvm-project/libcxx/include/__expected/expected.h (revision 1ac55f4cb0001fed92329746c730aa9a947c09a5)
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>
17bdd1243dSDimitry Andric #include <__memory/addressof.h>
18bdd1243dSDimitry Andric #include <__memory/construct_at.h>
19bdd1243dSDimitry Andric #include <__type_traits/conjunction.h>
20bdd1243dSDimitry Andric #include <__type_traits/disjunction.h>
21bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h>
22bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h>
23bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h>
24bdd1243dSDimitry Andric #include <__type_traits/is_copy_assignable.h>
25bdd1243dSDimitry Andric #include <__type_traits/is_copy_constructible.h>
26bdd1243dSDimitry Andric #include <__type_traits/is_default_constructible.h>
27bdd1243dSDimitry Andric #include <__type_traits/is_function.h>
28bdd1243dSDimitry Andric #include <__type_traits/is_move_assignable.h>
29bdd1243dSDimitry Andric #include <__type_traits/is_move_constructible.h>
30bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
31bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_assignable.h>
32bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_copy_constructible.h>
33bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_default_constructible.h>
34bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_assignable.h>
35bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_move_constructible.h>
36bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
37bdd1243dSDimitry Andric #include <__type_traits/is_same.h>
38bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h>
39bdd1243dSDimitry Andric #include <__type_traits/is_trivially_copy_constructible.h>
40bdd1243dSDimitry Andric #include <__type_traits/is_trivially_destructible.h>
41bdd1243dSDimitry Andric #include <__type_traits/is_trivially_move_constructible.h>
42bdd1243dSDimitry Andric #include <__type_traits/is_void.h>
43bdd1243dSDimitry Andric #include <__type_traits/lazy.h>
44bdd1243dSDimitry Andric #include <__type_traits/negation.h>
45bdd1243dSDimitry Andric #include <__type_traits/remove_cv.h>
46bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
47bdd1243dSDimitry Andric #include <__utility/exception_guard.h>
48bdd1243dSDimitry Andric #include <__utility/forward.h>
49bdd1243dSDimitry Andric #include <__utility/in_place.h>
50bdd1243dSDimitry Andric #include <__utility/move.h>
51bdd1243dSDimitry Andric #include <__utility/swap.h>
52bdd1243dSDimitry Andric #include <cstdlib> // for std::abort
53bdd1243dSDimitry Andric #include <initializer_list>
54bdd1243dSDimitry Andric 
55bdd1243dSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
56bdd1243dSDimitry Andric #  pragma GCC system_header
57bdd1243dSDimitry Andric #endif
58bdd1243dSDimitry Andric 
59bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 23
60bdd1243dSDimitry Andric 
61bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
62bdd1243dSDimitry Andric 
63bdd1243dSDimitry Andric namespace __expected {
64bdd1243dSDimitry Andric 
65bdd1243dSDimitry Andric template <class _Err, class _Arg>
66bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
67bdd1243dSDimitry Andric #  ifndef _LIBCPP_NO_EXCEPTIONS
68bdd1243dSDimitry Andric   throw bad_expected_access<_Err>(std::forward<_Arg>(__arg));
69bdd1243dSDimitry Andric #  else
70bdd1243dSDimitry Andric   (void)__arg;
71bdd1243dSDimitry Andric   std::abort();
72bdd1243dSDimitry Andric #  endif
73bdd1243dSDimitry Andric }
74bdd1243dSDimitry Andric 
75bdd1243dSDimitry Andric } // namespace __expected
76bdd1243dSDimitry Andric 
77bdd1243dSDimitry Andric template <class _Tp, class _Err>
78bdd1243dSDimitry Andric class expected {
79bdd1243dSDimitry Andric   static_assert(
80bdd1243dSDimitry Andric       !is_reference_v<_Tp> &&
81bdd1243dSDimitry Andric           !is_function_v<_Tp> &&
82bdd1243dSDimitry Andric           !is_same_v<remove_cv_t<_Tp>, in_place_t> &&
83bdd1243dSDimitry Andric           !is_same_v<remove_cv_t<_Tp>, unexpect_t> &&
84bdd1243dSDimitry Andric           !__is_std_unexpected<remove_cv_t<_Tp>>::value &&
85bdd1243dSDimitry Andric           __valid_std_unexpected<_Err>::value
86bdd1243dSDimitry Andric       ,
87bdd1243dSDimitry Andric       "[expected.object.general] A program that instantiates the definition of template expected<T, E> for a "
88bdd1243dSDimitry Andric       "reference type, a function type, or for possibly cv-qualified types in_place_t, unexpect_t, or a "
89bdd1243dSDimitry Andric       "specialization of unexpected for the T parameter is ill-formed. A program that instantiates the "
90bdd1243dSDimitry Andric       "definition of the template expected<T, E> with a type for the E parameter that is not a valid "
91bdd1243dSDimitry Andric       "template argument for unexpected is ill-formed.");
92bdd1243dSDimitry Andric 
93bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
94bdd1243dSDimitry Andric   friend class expected;
95bdd1243dSDimitry Andric 
96bdd1243dSDimitry Andric public:
97bdd1243dSDimitry Andric   using value_type      = _Tp;
98bdd1243dSDimitry Andric   using error_type      = _Err;
99bdd1243dSDimitry Andric   using unexpected_type = unexpected<_Err>;
100bdd1243dSDimitry Andric 
101bdd1243dSDimitry Andric   template <class _Up>
102bdd1243dSDimitry Andric   using rebind = expected<_Up, error_type>;
103bdd1243dSDimitry Andric 
104bdd1243dSDimitry Andric   // [expected.object.ctor], constructors
105bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected()
106bdd1243dSDimitry Andric     noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
107bdd1243dSDimitry Andric     requires is_default_constructible_v<_Tp>
108bdd1243dSDimitry Andric       : __has_val_(true) {
109bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__val_));
110bdd1243dSDimitry Andric   }
111bdd1243dSDimitry Andric 
112bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
113bdd1243dSDimitry Andric 
114bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
115bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Tp> &&
116bdd1243dSDimitry Andric              is_copy_constructible_v<_Err> &&
117bdd1243dSDimitry Andric              is_trivially_copy_constructible_v<_Tp> &&
118bdd1243dSDimitry Andric              is_trivially_copy_constructible_v<_Err>)
119bdd1243dSDimitry Andric   = default;
120bdd1243dSDimitry Andric 
121bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other)
122bdd1243dSDimitry Andric     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
123bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
124bdd1243dSDimitry Andric              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
125bdd1243dSDimitry Andric       : __has_val_(__other.__has_val_) {
126bdd1243dSDimitry Andric     if (__has_val_) {
127bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
128bdd1243dSDimitry Andric     } else {
129bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
130bdd1243dSDimitry Andric     }
131bdd1243dSDimitry Andric   }
132bdd1243dSDimitry Andric 
133bdd1243dSDimitry Andric 
134bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
135bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
136bdd1243dSDimitry Andric               && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
137bdd1243dSDimitry Andric   = default;
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __other)
140bdd1243dSDimitry Andric     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
141bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
142bdd1243dSDimitry Andric              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
143bdd1243dSDimitry Andric       : __has_val_(__other.__has_val_) {
144bdd1243dSDimitry Andric     if (__has_val_) {
145bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
146bdd1243dSDimitry Andric     } else {
147bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
148bdd1243dSDimitry Andric     }
149bdd1243dSDimitry Andric   }
150bdd1243dSDimitry Andric 
151bdd1243dSDimitry Andric private:
152bdd1243dSDimitry Andric   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
153bdd1243dSDimitry Andric   using __can_convert =
154bdd1243dSDimitry Andric       _And< is_constructible<_Tp, _UfQual>,
155bdd1243dSDimitry Andric             is_constructible<_Err, _OtherErrQual>,
156bdd1243dSDimitry Andric             _Not<is_constructible<_Tp, expected<_Up, _OtherErr>&>>,
157bdd1243dSDimitry Andric             _Not<is_constructible<_Tp, expected<_Up, _OtherErr>>>,
158bdd1243dSDimitry Andric             _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>&>>,
159bdd1243dSDimitry Andric             _Not<is_constructible<_Tp, const expected<_Up, _OtherErr>>>,
160bdd1243dSDimitry Andric             _Not<is_convertible<expected<_Up, _OtherErr>&, _Tp>>,
161bdd1243dSDimitry Andric             _Not<is_convertible<expected<_Up, _OtherErr>&&, _Tp>>,
162bdd1243dSDimitry Andric             _Not<is_convertible<const expected<_Up, _OtherErr>&, _Tp>>,
163bdd1243dSDimitry Andric             _Not<is_convertible<const expected<_Up, _OtherErr>&&, _Tp>>,
164bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
165bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
166bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
167bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>> >;
168bdd1243dSDimitry Andric 
169bdd1243dSDimitry Andric 
170bdd1243dSDimitry Andric public:
171bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
172bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, const _Up&, const _OtherErr&>::value
173bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _Up&, _Tp> ||
174bdd1243dSDimitry Andric                                            !is_convertible_v<const _OtherErr&, _Err>)
175bdd1243dSDimitry Andric   expected(const expected<_Up, _OtherErr>& __other)
176bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
177bdd1243dSDimitry Andric              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
178bdd1243dSDimitry Andric       : __has_val_(__other.__has_val_) {
179bdd1243dSDimitry Andric     if (__has_val_) {
180bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__val_), __other.__union_.__val_);
181bdd1243dSDimitry Andric     } else {
182bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __other.__union_.__unex_);
183bdd1243dSDimitry Andric     }
184bdd1243dSDimitry Andric   }
185bdd1243dSDimitry Andric 
186bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
187bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
188bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
189bdd1243dSDimitry Andric   expected(expected<_Up, _OtherErr>&& __other)
190bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
191bdd1243dSDimitry Andric       : __has_val_(__other.__has_val_) {
192bdd1243dSDimitry Andric     if (__has_val_) {
193bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__val_), std::move(__other.__union_.__val_));
194bdd1243dSDimitry Andric     } else {
195bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__other.__union_.__unex_));
196bdd1243dSDimitry Andric     }
197bdd1243dSDimitry Andric   }
198bdd1243dSDimitry Andric 
199bdd1243dSDimitry Andric   template <class _Up = _Tp>
200bdd1243dSDimitry Andric     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
201bdd1243dSDimitry Andric              !__is_std_unexpected<remove_cvref_t<_Up>>::value && is_constructible_v<_Tp, _Up>)
202bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
203bdd1243dSDimitry Andric   expected(_Up&& __u)
204bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
205bdd1243dSDimitry Andric       : __has_val_(true) {
206bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__val_), std::forward<_Up>(__u));
207bdd1243dSDimitry Andric   }
208bdd1243dSDimitry Andric 
209bdd1243dSDimitry Andric 
210bdd1243dSDimitry Andric   template <class _OtherErr>
211bdd1243dSDimitry Andric     requires is_constructible_v<_Err, const _OtherErr&>
212bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
213bdd1243dSDimitry Andric   expected(const unexpected<_OtherErr>& __unex)
214bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
215bdd1243dSDimitry Andric       : __has_val_(false) {
216bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), __unex.error());
217bdd1243dSDimitry Andric   }
218bdd1243dSDimitry Andric 
219bdd1243dSDimitry Andric   template <class _OtherErr>
220bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _OtherErr>
221bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
222bdd1243dSDimitry Andric   expected(unexpected<_OtherErr>&& __unex)
223bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
224bdd1243dSDimitry Andric       : __has_val_(false) {
225bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
226bdd1243dSDimitry Andric   }
227bdd1243dSDimitry Andric 
228bdd1243dSDimitry Andric   template <class... _Args>
229bdd1243dSDimitry Andric     requires is_constructible_v<_Tp, _Args...>
230bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
231bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
232bdd1243dSDimitry Andric       : __has_val_(true) {
233bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
234bdd1243dSDimitry Andric   }
235bdd1243dSDimitry Andric 
236bdd1243dSDimitry Andric   template <class _Up, class... _Args>
237bdd1243dSDimitry Andric     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
238bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit
239bdd1243dSDimitry Andric   expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
240bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
241bdd1243dSDimitry Andric       : __has_val_(true) {
242bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
243bdd1243dSDimitry Andric   }
244bdd1243dSDimitry Andric 
245bdd1243dSDimitry Andric   template <class... _Args>
246bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _Args...>
247bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
248bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, _Args...>)  // strengthened
249bdd1243dSDimitry Andric       : __has_val_(false) {
250bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
251bdd1243dSDimitry Andric   }
252bdd1243dSDimitry Andric 
253bdd1243dSDimitry Andric   template <class _Up, class... _Args>
254bdd1243dSDimitry Andric     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
255bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit
256bdd1243dSDimitry Andric   expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
257bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
258bdd1243dSDimitry Andric       : __has_val_(false) {
259bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
260bdd1243dSDimitry Andric   }
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric   // [expected.object.dtor], destructor
263bdd1243dSDimitry Andric 
264bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
265bdd1243dSDimitry Andric     requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
266bdd1243dSDimitry Andric   = default;
267bdd1243dSDimitry Andric 
268bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
269bdd1243dSDimitry Andric     requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
270bdd1243dSDimitry Andric   {
271bdd1243dSDimitry Andric     if (__has_val_) {
272bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
273bdd1243dSDimitry Andric     } else {
274bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
275bdd1243dSDimitry Andric     }
276bdd1243dSDimitry Andric   }
277bdd1243dSDimitry Andric 
278bdd1243dSDimitry Andric private:
279bdd1243dSDimitry Andric   template <class _T1, class _T2, class... _Args>
280bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) {
281bdd1243dSDimitry Andric     if constexpr (is_nothrow_constructible_v<_T1, _Args...>) {
282bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
283bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
284bdd1243dSDimitry Andric     } else if constexpr (is_nothrow_move_constructible_v<_T1>) {
285bdd1243dSDimitry Andric       _T1 __tmp(std::forward<_Args>(__args)...);
286bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
287bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::move(__tmp));
288bdd1243dSDimitry Andric     } else {
289bdd1243dSDimitry Andric       static_assert(
290bdd1243dSDimitry Andric           is_nothrow_move_constructible_v<_T2>,
291bdd1243dSDimitry Andric           "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
292bdd1243dSDimitry Andric           "be reverted to the previous state in case an exception is thrown during the assignment.");
293bdd1243dSDimitry Andric       _T2 __tmp(std::move(__oldval));
294bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__oldval));
295*1ac55f4cSDimitry Andric       auto __trans =
296*1ac55f4cSDimitry Andric           std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
297bdd1243dSDimitry Andric       std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
298bdd1243dSDimitry Andric       __trans.__complete();
299bdd1243dSDimitry Andric     }
300bdd1243dSDimitry Andric   }
301bdd1243dSDimitry Andric 
302bdd1243dSDimitry Andric public:
303bdd1243dSDimitry Andric   // [expected.object.assign], assignment
304bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
305bdd1243dSDimitry Andric 
306bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
307bdd1243dSDimitry Andric     noexcept(is_nothrow_copy_assignable_v<_Tp> &&
308bdd1243dSDimitry Andric              is_nothrow_copy_constructible_v<_Tp> &&
309bdd1243dSDimitry Andric              is_nothrow_copy_assignable_v<_Err> &&
310bdd1243dSDimitry Andric              is_nothrow_copy_constructible_v<_Err>) // strengthened
311bdd1243dSDimitry Andric     requires(is_copy_assignable_v<_Tp> &&
312bdd1243dSDimitry Andric              is_copy_constructible_v<_Tp> &&
313bdd1243dSDimitry Andric              is_copy_assignable_v<_Err> &&
314bdd1243dSDimitry Andric              is_copy_constructible_v<_Err> &&
315bdd1243dSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> ||
316bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Err>))
317bdd1243dSDimitry Andric   {
318bdd1243dSDimitry Andric     if (__has_val_ && __rhs.__has_val_) {
319bdd1243dSDimitry Andric       __union_.__val_ = __rhs.__union_.__val_;
320bdd1243dSDimitry Andric     } else if (__has_val_) {
321bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_);
322bdd1243dSDimitry Andric     } else if (__rhs.__has_val_) {
323bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_);
324bdd1243dSDimitry Andric     } else {
325bdd1243dSDimitry Andric       __union_.__unex_ = __rhs.__union_.__unex_;
326bdd1243dSDimitry Andric     }
327bdd1243dSDimitry Andric     // note: only reached if no exception+rollback was done inside __reinit_expected
328bdd1243dSDimitry Andric     __has_val_ = __rhs.__has_val_;
329bdd1243dSDimitry Andric     return *this;
330bdd1243dSDimitry Andric   }
331bdd1243dSDimitry Andric 
332bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
333bdd1243dSDimitry Andric     noexcept(is_nothrow_move_assignable_v<_Tp> &&
334bdd1243dSDimitry Andric              is_nothrow_move_constructible_v<_Tp> &&
335bdd1243dSDimitry Andric              is_nothrow_move_assignable_v<_Err> &&
336bdd1243dSDimitry Andric              is_nothrow_move_constructible_v<_Err>)
337bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Tp> &&
338bdd1243dSDimitry Andric              is_move_assignable_v<_Tp> &&
339bdd1243dSDimitry Andric              is_move_constructible_v<_Err> &&
340bdd1243dSDimitry Andric              is_move_assignable_v<_Err> &&
341bdd1243dSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> ||
342bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Err>))
343bdd1243dSDimitry Andric   {
344bdd1243dSDimitry Andric     if (__has_val_ && __rhs.__has_val_) {
345bdd1243dSDimitry Andric       __union_.__val_ = std::move(__rhs.__union_.__val_);
346bdd1243dSDimitry Andric     } else if (__has_val_) {
347bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_));
348bdd1243dSDimitry Andric     } else if (__rhs.__has_val_) {
349bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_));
350bdd1243dSDimitry Andric     } else {
351bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__rhs.__union_.__unex_);
352bdd1243dSDimitry Andric     }
353bdd1243dSDimitry Andric     // note: only reached if no exception+rollback was done inside __reinit_expected
354bdd1243dSDimitry Andric     __has_val_ = __rhs.__has_val_;
355bdd1243dSDimitry Andric     return *this;
356bdd1243dSDimitry Andric   }
357bdd1243dSDimitry Andric 
358bdd1243dSDimitry Andric   template <class _Up = _Tp>
359bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(_Up&& __v)
360bdd1243dSDimitry Andric     requires(!is_same_v<expected, remove_cvref_t<_Up>> &&
361bdd1243dSDimitry Andric              !__is_std_unexpected<remove_cvref_t<_Up>>::value &&
362bdd1243dSDimitry Andric              is_constructible_v<_Tp, _Up> &&
363bdd1243dSDimitry Andric              is_assignable_v<_Tp&, _Up> &&
364bdd1243dSDimitry Andric              (is_nothrow_constructible_v<_Tp, _Up> ||
365bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Tp> ||
366bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Err>))
367bdd1243dSDimitry Andric   {
368bdd1243dSDimitry Andric     if (__has_val_) {
369bdd1243dSDimitry Andric       __union_.__val_ = std::forward<_Up>(__v);
370bdd1243dSDimitry Andric     } else {
371bdd1243dSDimitry Andric       __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v));
372bdd1243dSDimitry Andric       __has_val_ = true;
373bdd1243dSDimitry Andric     }
374bdd1243dSDimitry Andric     return *this;
375bdd1243dSDimitry Andric   }
376bdd1243dSDimitry Andric 
377bdd1243dSDimitry Andric private:
378bdd1243dSDimitry Andric   template <class _OtherErrQual>
379bdd1243dSDimitry Andric   static constexpr bool __can_assign_from_unexpected =
380bdd1243dSDimitry Andric       _And< is_constructible<_Err, _OtherErrQual>,
381bdd1243dSDimitry Andric             is_assignable<_Err&, _OtherErrQual>,
382bdd1243dSDimitry Andric             _Lazy<_Or,
383bdd1243dSDimitry Andric                   is_nothrow_constructible<_Err, _OtherErrQual>,
384bdd1243dSDimitry Andric                   is_nothrow_move_constructible<_Tp>,
385bdd1243dSDimitry Andric                   is_nothrow_move_constructible<_Err>> >::value;
386bdd1243dSDimitry Andric 
387bdd1243dSDimitry Andric public:
388bdd1243dSDimitry Andric   template <class _OtherErr>
389bdd1243dSDimitry Andric     requires(__can_assign_from_unexpected<const _OtherErr&>)
390bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
391bdd1243dSDimitry Andric     if (__has_val_) {
392bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, __un.error());
393bdd1243dSDimitry Andric       __has_val_ = false;
394bdd1243dSDimitry Andric     } else {
395bdd1243dSDimitry Andric       __union_.__unex_ = __un.error();
396bdd1243dSDimitry Andric     }
397bdd1243dSDimitry Andric     return *this;
398bdd1243dSDimitry Andric   }
399bdd1243dSDimitry Andric 
400bdd1243dSDimitry Andric   template <class _OtherErr>
401bdd1243dSDimitry Andric     requires(__can_assign_from_unexpected<_OtherErr>)
402bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
403bdd1243dSDimitry Andric     if (__has_val_) {
404bdd1243dSDimitry Andric       __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error()));
405bdd1243dSDimitry Andric       __has_val_ = false;
406bdd1243dSDimitry Andric     } else {
407bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__un.error());
408bdd1243dSDimitry Andric     }
409bdd1243dSDimitry Andric     return *this;
410bdd1243dSDimitry Andric   }
411bdd1243dSDimitry Andric 
412bdd1243dSDimitry Andric   template <class... _Args>
413bdd1243dSDimitry Andric     requires is_nothrow_constructible_v<_Tp, _Args...>
414bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
415bdd1243dSDimitry Andric     if (__has_val_) {
416bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
417bdd1243dSDimitry Andric     } else {
418bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
419bdd1243dSDimitry Andric       __has_val_ = true;
420bdd1243dSDimitry Andric     }
421bdd1243dSDimitry Andric     return *std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
422bdd1243dSDimitry Andric   }
423bdd1243dSDimitry Andric 
424bdd1243dSDimitry Andric   template <class _Up, class... _Args>
425bdd1243dSDimitry Andric     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
426bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
427bdd1243dSDimitry Andric     if (__has_val_) {
428bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__val_));
429bdd1243dSDimitry Andric     } else {
430bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
431bdd1243dSDimitry Andric       __has_val_ = true;
432bdd1243dSDimitry Andric     }
433bdd1243dSDimitry Andric     return *std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
434bdd1243dSDimitry Andric   }
435bdd1243dSDimitry Andric 
436bdd1243dSDimitry Andric 
437bdd1243dSDimitry Andric public:
438bdd1243dSDimitry Andric   // [expected.object.swap], swap
439bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs)
440bdd1243dSDimitry Andric     noexcept(is_nothrow_move_constructible_v<_Tp> &&
441bdd1243dSDimitry Andric              is_nothrow_swappable_v<_Tp> &&
442bdd1243dSDimitry Andric              is_nothrow_move_constructible_v<_Err> &&
443bdd1243dSDimitry Andric              is_nothrow_swappable_v<_Err>)
444bdd1243dSDimitry Andric     requires(is_swappable_v<_Tp> &&
445bdd1243dSDimitry Andric              is_swappable_v<_Err> &&
446bdd1243dSDimitry Andric              is_move_constructible_v<_Tp> &&
447bdd1243dSDimitry Andric              is_move_constructible_v<_Err> &&
448bdd1243dSDimitry Andric              (is_nothrow_move_constructible_v<_Tp> ||
449bdd1243dSDimitry Andric               is_nothrow_move_constructible_v<_Err>))
450bdd1243dSDimitry Andric   {
451bdd1243dSDimitry Andric     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
452bdd1243dSDimitry Andric       if constexpr (is_nothrow_move_constructible_v<_Err>) {
453bdd1243dSDimitry Andric         _Err __tmp(std::move(__with_err.__union_.__unex_));
454bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_err.__union_.__unex_));
455*1ac55f4cSDimitry Andric         auto __trans = std::__make_exception_guard([&] {
456bdd1243dSDimitry Andric           std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
457bdd1243dSDimitry Andric         });
458bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
459bdd1243dSDimitry Andric         __trans.__complete();
460bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_val.__union_.__val_));
461bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp));
462bdd1243dSDimitry Andric       } else {
463bdd1243dSDimitry Andric         static_assert(is_nothrow_move_constructible_v<_Tp>,
464bdd1243dSDimitry Andric                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
465bdd1243dSDimitry Andric                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
466bdd1243dSDimitry Andric         _Tp __tmp(std::move(__with_val.__union_.__val_));
467bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_val.__union_.__val_));
468*1ac55f4cSDimitry Andric         auto __trans = std::__make_exception_guard([&] {
469bdd1243dSDimitry Andric           std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp));
470bdd1243dSDimitry Andric         });
471bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
472bdd1243dSDimitry Andric         __trans.__complete();
473bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__with_err.__union_.__unex_));
474bdd1243dSDimitry Andric         std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp));
475bdd1243dSDimitry Andric       }
476bdd1243dSDimitry Andric       __with_val.__has_val_ = false;
477bdd1243dSDimitry Andric       __with_err.__has_val_ = true;
478bdd1243dSDimitry Andric     };
479bdd1243dSDimitry Andric 
480bdd1243dSDimitry Andric     if (__has_val_) {
481bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
482bdd1243dSDimitry Andric         using std::swap;
483bdd1243dSDimitry Andric         swap(__union_.__val_, __rhs.__union_.__val_);
484bdd1243dSDimitry Andric       } else {
485bdd1243dSDimitry Andric         __swap_val_unex_impl(*this, __rhs);
486bdd1243dSDimitry Andric       }
487bdd1243dSDimitry Andric     } else {
488bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
489bdd1243dSDimitry Andric         __swap_val_unex_impl(__rhs, *this);
490bdd1243dSDimitry Andric       } else {
491bdd1243dSDimitry Andric         using std::swap;
492bdd1243dSDimitry Andric         swap(__union_.__unex_, __rhs.__union_.__unex_);
493bdd1243dSDimitry Andric       }
494bdd1243dSDimitry Andric     }
495bdd1243dSDimitry Andric   }
496bdd1243dSDimitry Andric 
497bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
498bdd1243dSDimitry Andric     noexcept(noexcept(__x.swap(__y)))
499bdd1243dSDimitry Andric     requires requires { __x.swap(__y); }
500bdd1243dSDimitry Andric   {
501bdd1243dSDimitry Andric     __x.swap(__y);
502bdd1243dSDimitry Andric   }
503bdd1243dSDimitry Andric 
504bdd1243dSDimitry Andric   // [expected.object.obs], observers
505bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
506bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value");
507bdd1243dSDimitry Andric     return std::addressof(__union_.__val_);
508bdd1243dSDimitry Andric   }
509bdd1243dSDimitry Andric 
510bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
511bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator-> requires the expected to contain a value");
512bdd1243dSDimitry Andric     return std::addressof(__union_.__val_);
513bdd1243dSDimitry Andric   }
514bdd1243dSDimitry Andric 
515bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
516bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
517bdd1243dSDimitry Andric     return __union_.__val_;
518bdd1243dSDimitry Andric   }
519bdd1243dSDimitry Andric 
520bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
521bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
522bdd1243dSDimitry Andric     return __union_.__val_;
523bdd1243dSDimitry Andric   }
524bdd1243dSDimitry Andric 
525bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
526bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
527bdd1243dSDimitry Andric     return std::move(__union_.__val_);
528bdd1243dSDimitry Andric   }
529bdd1243dSDimitry Andric 
530bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
531bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
532bdd1243dSDimitry Andric     return std::move(__union_.__val_);
533bdd1243dSDimitry Andric   }
534bdd1243dSDimitry Andric 
535bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
536bdd1243dSDimitry Andric 
537bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
538bdd1243dSDimitry Andric 
539bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
540bdd1243dSDimitry Andric     if (!__has_val_) {
541bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
542bdd1243dSDimitry Andric     }
543bdd1243dSDimitry Andric     return __union_.__val_;
544bdd1243dSDimitry Andric   }
545bdd1243dSDimitry Andric 
546bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
547bdd1243dSDimitry Andric     if (!__has_val_) {
548bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
549bdd1243dSDimitry Andric     }
550bdd1243dSDimitry Andric     return __union_.__val_;
551bdd1243dSDimitry Andric   }
552bdd1243dSDimitry Andric 
553bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
554bdd1243dSDimitry Andric     if (!__has_val_) {
555bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
556bdd1243dSDimitry Andric     }
557bdd1243dSDimitry Andric     return std::move(__union_.__val_);
558bdd1243dSDimitry Andric   }
559bdd1243dSDimitry Andric 
560bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
561bdd1243dSDimitry Andric     if (!__has_val_) {
562bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
563bdd1243dSDimitry Andric     }
564bdd1243dSDimitry Andric     return std::move(__union_.__val_);
565bdd1243dSDimitry Andric   }
566bdd1243dSDimitry Andric 
567bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
568bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
569bdd1243dSDimitry Andric     return __union_.__unex_;
570bdd1243dSDimitry Andric   }
571bdd1243dSDimitry Andric 
572bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
573bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
574bdd1243dSDimitry Andric     return __union_.__unex_;
575bdd1243dSDimitry Andric   }
576bdd1243dSDimitry Andric 
577bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
578bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
579bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
580bdd1243dSDimitry Andric   }
581bdd1243dSDimitry Andric 
582bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
583bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
584bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
585bdd1243dSDimitry Andric   }
586bdd1243dSDimitry Andric 
587bdd1243dSDimitry Andric   template <class _Up>
588bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
589bdd1243dSDimitry Andric     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
590bdd1243dSDimitry Andric     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
591bdd1243dSDimitry Andric     return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
592bdd1243dSDimitry Andric   }
593bdd1243dSDimitry Andric 
594bdd1243dSDimitry Andric   template <class _Up>
595bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
596bdd1243dSDimitry Andric     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
597bdd1243dSDimitry Andric     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
598bdd1243dSDimitry Andric     return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
599bdd1243dSDimitry Andric   }
600bdd1243dSDimitry Andric 
601bdd1243dSDimitry Andric   // [expected.object.eq], equality operators
602bdd1243dSDimitry Andric   template <class _T2, class _E2>
603bdd1243dSDimitry Andric     requires(!is_void_v<_T2>)
604bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
605bdd1243dSDimitry Andric     if (__x.__has_val_ != __y.__has_val_) {
606bdd1243dSDimitry Andric       return false;
607bdd1243dSDimitry Andric     } else {
608bdd1243dSDimitry Andric       if (__x.__has_val_) {
609bdd1243dSDimitry Andric         return __x.__union_.__val_ == __y.__union_.__val_;
610bdd1243dSDimitry Andric       } else {
611bdd1243dSDimitry Andric         return __x.__union_.__unex_ == __y.__union_.__unex_;
612bdd1243dSDimitry Andric       }
613bdd1243dSDimitry Andric     }
614bdd1243dSDimitry Andric   }
615bdd1243dSDimitry Andric 
616bdd1243dSDimitry Andric   template <class _T2>
617bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
618bdd1243dSDimitry Andric     return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
619bdd1243dSDimitry Andric   }
620bdd1243dSDimitry Andric 
621bdd1243dSDimitry Andric   template <class _E2>
622bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
623bdd1243dSDimitry Andric     return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
624bdd1243dSDimitry Andric   }
625bdd1243dSDimitry Andric 
626bdd1243dSDimitry Andric private:
627bdd1243dSDimitry Andric   struct __empty_t {};
628bdd1243dSDimitry Andric   // use named union because [[no_unique_address]] cannot be applied to an unnamed union
629bdd1243dSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
630bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
631bdd1243dSDimitry Andric 
632bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
633bdd1243dSDimitry Andric       requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
634bdd1243dSDimitry Andric     = default;
635bdd1243dSDimitry Andric 
636bdd1243dSDimitry Andric     // the expected's destructor handles this
637bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
638bdd1243dSDimitry Andric       requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
639bdd1243dSDimitry Andric     {}
640bdd1243dSDimitry Andric 
641bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
642bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_;
643bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
644bdd1243dSDimitry Andric   } __union_;
645bdd1243dSDimitry Andric 
646bdd1243dSDimitry Andric   bool __has_val_;
647bdd1243dSDimitry Andric };
648bdd1243dSDimitry Andric 
649bdd1243dSDimitry Andric template <class _Tp, class _Err>
650bdd1243dSDimitry Andric   requires is_void_v<_Tp>
651bdd1243dSDimitry Andric class expected<_Tp, _Err> {
652bdd1243dSDimitry Andric   static_assert(__valid_std_unexpected<_Err>::value,
653bdd1243dSDimitry Andric                 "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
654bdd1243dSDimitry Andric                 "valid argument for unexpected<E> is ill-formed");
655bdd1243dSDimitry Andric 
656bdd1243dSDimitry Andric   template <class, class>
657bdd1243dSDimitry Andric   friend class expected;
658bdd1243dSDimitry Andric 
659bdd1243dSDimitry Andric   template <class _Up, class _OtherErr, class _OtherErrQual>
660bdd1243dSDimitry Andric   using __can_convert =
661bdd1243dSDimitry Andric       _And< is_void<_Up>,
662bdd1243dSDimitry Andric             is_constructible<_Err, _OtherErrQual>,
663bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>&>>,
664bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, expected<_Up, _OtherErr>>>,
665bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
666bdd1243dSDimitry Andric             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
667bdd1243dSDimitry Andric 
668bdd1243dSDimitry Andric public:
669bdd1243dSDimitry Andric   using value_type      = _Tp;
670bdd1243dSDimitry Andric   using error_type      = _Err;
671bdd1243dSDimitry Andric   using unexpected_type = unexpected<_Err>;
672bdd1243dSDimitry Andric 
673bdd1243dSDimitry Andric   template <class _Up>
674bdd1243dSDimitry Andric   using rebind = expected<_Up, error_type>;
675bdd1243dSDimitry Andric 
676bdd1243dSDimitry Andric   // [expected.void.ctor], constructors
677bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {}
678bdd1243dSDimitry Andric 
679bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
680bdd1243dSDimitry Andric 
681bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
682bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
683bdd1243dSDimitry Andric   = default;
684bdd1243dSDimitry Andric 
685bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
686bdd1243dSDimitry Andric     noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
687bdd1243dSDimitry Andric     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
688bdd1243dSDimitry Andric       : __has_val_(__rhs.__has_val_) {
689bdd1243dSDimitry Andric     if (!__rhs.__has_val_) {
690bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
691bdd1243dSDimitry Andric     }
692bdd1243dSDimitry Andric   }
693bdd1243dSDimitry Andric 
694bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
695bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
696bdd1243dSDimitry Andric   = default;
697bdd1243dSDimitry Andric 
698bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
699bdd1243dSDimitry Andric     noexcept(is_nothrow_move_constructible_v<_Err>)
700bdd1243dSDimitry Andric     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
701bdd1243dSDimitry Andric       : __has_val_(__rhs.__has_val_) {
702bdd1243dSDimitry Andric     if (!__rhs.__has_val_) {
703bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
704bdd1243dSDimitry Andric     }
705bdd1243dSDimitry Andric   }
706bdd1243dSDimitry Andric 
707bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
708bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
709bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
710bdd1243dSDimitry Andric   expected(const expected<_Up, _OtherErr>& __rhs)
711bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
712bdd1243dSDimitry Andric       : __has_val_(__rhs.__has_val_) {
713bdd1243dSDimitry Andric     if (!__rhs.__has_val_) {
714bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
715bdd1243dSDimitry Andric     }
716bdd1243dSDimitry Andric   }
717bdd1243dSDimitry Andric 
718bdd1243dSDimitry Andric   template <class _Up, class _OtherErr>
719bdd1243dSDimitry Andric     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
720bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
721bdd1243dSDimitry Andric   expected(expected<_Up, _OtherErr>&& __rhs)
722bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
723bdd1243dSDimitry Andric       : __has_val_(__rhs.__has_val_) {
724bdd1243dSDimitry Andric     if (!__rhs.__has_val_) {
725bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
726bdd1243dSDimitry Andric     }
727bdd1243dSDimitry Andric   }
728bdd1243dSDimitry Andric 
729bdd1243dSDimitry Andric   template <class _OtherErr>
730bdd1243dSDimitry Andric     requires is_constructible_v<_Err, const _OtherErr&>
731bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
732bdd1243dSDimitry Andric   expected(const unexpected<_OtherErr>& __unex)
733bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
734bdd1243dSDimitry Andric       : __has_val_(false) {
735bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), __unex.error());
736bdd1243dSDimitry Andric   }
737bdd1243dSDimitry Andric 
738bdd1243dSDimitry Andric   template <class _OtherErr>
739bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _OtherErr>
740bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
741bdd1243dSDimitry Andric   expected(unexpected<_OtherErr>&& __unex)
742bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
743bdd1243dSDimitry Andric       : __has_val_(false) {
744bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), std::move(__unex.error()));
745bdd1243dSDimitry Andric   }
746bdd1243dSDimitry Andric 
747bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
748bdd1243dSDimitry Andric 
749bdd1243dSDimitry Andric   template <class... _Args>
750bdd1243dSDimitry Andric     requires is_constructible_v<_Err, _Args...>
751bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
752bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
753bdd1243dSDimitry Andric       : __has_val_(false) {
754bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), std::forward<_Args>(__args)...);
755bdd1243dSDimitry Andric   }
756bdd1243dSDimitry Andric 
757bdd1243dSDimitry Andric   template <class _Up, class... _Args>
758bdd1243dSDimitry Andric     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
759bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
760bdd1243dSDimitry Andric     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
761bdd1243dSDimitry Andric       : __has_val_(false) {
762bdd1243dSDimitry Andric     std::construct_at(std::addressof(__union_.__unex_), __il, std::forward<_Args>(__args)...);
763bdd1243dSDimitry Andric   }
764bdd1243dSDimitry Andric 
765bdd1243dSDimitry Andric   // [expected.void.dtor], destructor
766bdd1243dSDimitry Andric 
767bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
768bdd1243dSDimitry Andric     requires is_trivially_destructible_v<_Err>
769bdd1243dSDimitry Andric   = default;
770bdd1243dSDimitry Andric 
771bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
772bdd1243dSDimitry Andric     requires(!is_trivially_destructible_v<_Err>)
773bdd1243dSDimitry Andric   {
774bdd1243dSDimitry Andric     if (!__has_val_) {
775bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
776bdd1243dSDimitry Andric     }
777bdd1243dSDimitry Andric   }
778bdd1243dSDimitry Andric 
779bdd1243dSDimitry Andric   // [expected.void.assign], assignment
780bdd1243dSDimitry Andric 
781bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
782bdd1243dSDimitry Andric 
783bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
784bdd1243dSDimitry Andric     noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
785bdd1243dSDimitry Andric     requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
786bdd1243dSDimitry Andric   {
787bdd1243dSDimitry Andric     if (__has_val_) {
788bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
789bdd1243dSDimitry Andric         std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
790bdd1243dSDimitry Andric         __has_val_ = false;
791bdd1243dSDimitry Andric       }
792bdd1243dSDimitry Andric     } else {
793bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
794bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__union_.__unex_));
795bdd1243dSDimitry Andric         __has_val_ = true;
796bdd1243dSDimitry Andric       } else {
797bdd1243dSDimitry Andric         __union_.__unex_ = __rhs.__union_.__unex_;
798bdd1243dSDimitry Andric       }
799bdd1243dSDimitry Andric     }
800bdd1243dSDimitry Andric     return *this;
801bdd1243dSDimitry Andric   }
802bdd1243dSDimitry Andric 
803bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&&) = delete;
804bdd1243dSDimitry Andric 
805bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(expected&& __rhs)
806bdd1243dSDimitry Andric     noexcept(is_nothrow_move_assignable_v<_Err> &&
807bdd1243dSDimitry Andric              is_nothrow_move_constructible_v<_Err>)
808bdd1243dSDimitry Andric     requires(is_move_assignable_v<_Err> &&
809bdd1243dSDimitry Andric              is_move_constructible_v<_Err>)
810bdd1243dSDimitry Andric   {
811bdd1243dSDimitry Andric     if (__has_val_) {
812bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
813bdd1243dSDimitry Andric         std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
814bdd1243dSDimitry Andric         __has_val_ = false;
815bdd1243dSDimitry Andric       }
816bdd1243dSDimitry Andric     } else {
817bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
818bdd1243dSDimitry Andric         std::destroy_at(std::addressof(__union_.__unex_));
819bdd1243dSDimitry Andric         __has_val_ = true;
820bdd1243dSDimitry Andric       } else {
821bdd1243dSDimitry Andric         __union_.__unex_ = std::move(__rhs.__union_.__unex_);
822bdd1243dSDimitry Andric       }
823bdd1243dSDimitry Andric     }
824bdd1243dSDimitry Andric     return *this;
825bdd1243dSDimitry Andric   }
826bdd1243dSDimitry Andric 
827bdd1243dSDimitry Andric   template <class _OtherErr>
828bdd1243dSDimitry Andric     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
829bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
830bdd1243dSDimitry Andric     if (__has_val_) {
831bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), __un.error());
832bdd1243dSDimitry Andric       __has_val_ = false;
833bdd1243dSDimitry Andric     } else {
834bdd1243dSDimitry Andric       __union_.__unex_ = __un.error();
835bdd1243dSDimitry Andric     }
836bdd1243dSDimitry Andric     return *this;
837bdd1243dSDimitry Andric   }
838bdd1243dSDimitry Andric 
839bdd1243dSDimitry Andric   template <class _OtherErr>
840bdd1243dSDimitry Andric     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
841bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
842bdd1243dSDimitry Andric     if (__has_val_) {
843bdd1243dSDimitry Andric       std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error()));
844bdd1243dSDimitry Andric       __has_val_ = false;
845bdd1243dSDimitry Andric     } else {
846bdd1243dSDimitry Andric       __union_.__unex_ = std::move(__un.error());
847bdd1243dSDimitry Andric     }
848bdd1243dSDimitry Andric     return *this;
849bdd1243dSDimitry Andric   }
850bdd1243dSDimitry Andric 
851bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
852bdd1243dSDimitry Andric     if (!__has_val_) {
853bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__union_.__unex_));
854bdd1243dSDimitry Andric       __has_val_ = true;
855bdd1243dSDimitry Andric     }
856bdd1243dSDimitry Andric   }
857bdd1243dSDimitry Andric 
858bdd1243dSDimitry Andric   // [expected.void.swap], swap
859bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs)
860bdd1243dSDimitry Andric     noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)
861bdd1243dSDimitry Andric     requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>)
862bdd1243dSDimitry Andric   {
863bdd1243dSDimitry Andric     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
864bdd1243dSDimitry Andric       std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
865bdd1243dSDimitry Andric       std::destroy_at(std::addressof(__with_err.__union_.__unex_));
866bdd1243dSDimitry Andric       __with_val.__has_val_ = false;
867bdd1243dSDimitry Andric       __with_err.__has_val_ = true;
868bdd1243dSDimitry Andric     };
869bdd1243dSDimitry Andric 
870bdd1243dSDimitry Andric     if (__has_val_) {
871bdd1243dSDimitry Andric       if (!__rhs.__has_val_) {
872bdd1243dSDimitry Andric         __swap_val_unex_impl(*this, __rhs);
873bdd1243dSDimitry Andric       }
874bdd1243dSDimitry Andric     } else {
875bdd1243dSDimitry Andric       if (__rhs.__has_val_) {
876bdd1243dSDimitry Andric         __swap_val_unex_impl(__rhs, *this);
877bdd1243dSDimitry Andric       } else {
878bdd1243dSDimitry Andric         using std::swap;
879bdd1243dSDimitry Andric         swap(__union_.__unex_, __rhs.__union_.__unex_);
880bdd1243dSDimitry Andric       }
881bdd1243dSDimitry Andric     }
882bdd1243dSDimitry Andric   }
883bdd1243dSDimitry Andric 
884bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr void swap(expected& __x, expected& __y)
885bdd1243dSDimitry Andric     noexcept(noexcept(__x.swap(__y)))
886bdd1243dSDimitry Andric     requires requires { __x.swap(__y); }
887bdd1243dSDimitry Andric   {
888bdd1243dSDimitry Andric     __x.swap(__y);
889bdd1243dSDimitry Andric   }
890bdd1243dSDimitry Andric 
891bdd1243dSDimitry Andric   // [expected.void.obs], observers
892bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
893bdd1243dSDimitry Andric 
894bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
895bdd1243dSDimitry Andric 
896bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
897bdd1243dSDimitry Andric     _LIBCPP_ASSERT(__has_val_, "expected::operator* requires the expected to contain a value");
898bdd1243dSDimitry Andric   }
899bdd1243dSDimitry Andric 
900bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
901bdd1243dSDimitry Andric     if (!__has_val_) {
902bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(__union_.__unex_);
903bdd1243dSDimitry Andric     }
904bdd1243dSDimitry Andric   }
905bdd1243dSDimitry Andric 
906bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
907bdd1243dSDimitry Andric     if (!__has_val_) {
908bdd1243dSDimitry Andric       __expected::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
909bdd1243dSDimitry Andric     }
910bdd1243dSDimitry Andric   }
911bdd1243dSDimitry Andric 
912bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
913bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
914bdd1243dSDimitry Andric     return __union_.__unex_;
915bdd1243dSDimitry Andric   }
916bdd1243dSDimitry Andric 
917bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
918bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
919bdd1243dSDimitry Andric     return __union_.__unex_;
920bdd1243dSDimitry Andric   }
921bdd1243dSDimitry Andric 
922bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
923bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
924bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
925bdd1243dSDimitry Andric   }
926bdd1243dSDimitry Andric 
927bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
928bdd1243dSDimitry Andric     _LIBCPP_ASSERT(!__has_val_, "expected::error requires the expected to contain an error");
929bdd1243dSDimitry Andric     return std::move(__union_.__unex_);
930bdd1243dSDimitry Andric   }
931bdd1243dSDimitry Andric 
932bdd1243dSDimitry Andric   // [expected.void.eq], equality operators
933bdd1243dSDimitry Andric   template <class _T2, class _E2>
934bdd1243dSDimitry Andric     requires is_void_v<_T2>
935bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
936bdd1243dSDimitry Andric     if (__x.__has_val_ != __y.__has_val_) {
937bdd1243dSDimitry Andric       return false;
938bdd1243dSDimitry Andric     } else {
939bdd1243dSDimitry Andric       return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
940bdd1243dSDimitry Andric     }
941bdd1243dSDimitry Andric   }
942bdd1243dSDimitry Andric 
943bdd1243dSDimitry Andric   template <class _E2>
944bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
945bdd1243dSDimitry Andric     return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
946bdd1243dSDimitry Andric   }
947bdd1243dSDimitry Andric 
948bdd1243dSDimitry Andric private:
949bdd1243dSDimitry Andric   struct __empty_t {};
950bdd1243dSDimitry Andric   // use named union because [[no_unique_address]] cannot be applied to an unnamed union
951bdd1243dSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS union __union_t {
952bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
953bdd1243dSDimitry Andric 
954bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
955bdd1243dSDimitry Andric       requires(is_trivially_destructible_v<_Err>)
956bdd1243dSDimitry Andric     = default;
957bdd1243dSDimitry Andric 
958bdd1243dSDimitry Andric     // the expected's destructor handles this
959bdd1243dSDimitry Andric     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
960bdd1243dSDimitry Andric       requires(!is_trivially_destructible_v<_Err>)
961bdd1243dSDimitry Andric     {}
962bdd1243dSDimitry Andric 
963bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
964bdd1243dSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
965bdd1243dSDimitry Andric   } __union_;
966bdd1243dSDimitry Andric 
967bdd1243dSDimitry Andric   bool __has_val_;
968bdd1243dSDimitry Andric };
969bdd1243dSDimitry Andric 
970bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD
971bdd1243dSDimitry Andric 
972bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 23
973bdd1243dSDimitry Andric 
974bdd1243dSDimitry Andric #endif // _LIBCPP___EXPECTED_EXPECTED_H
975