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