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