libstdc++
expected
Go to the documentation of this file.
1// <expected> -*- C++ -*-
2
3// Copyright The GNU Toolchain Authors.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/expected
26 * This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_EXPECTED
30#define _GLIBCXX_EXPECTED
31
32#pragma GCC system_header
33
34#if __cplusplus > 202002L && __cpp_concepts >= 202002L
35
36#include <initializer_list>
37#include <bits/exception.h> // exception
38#include <bits/invoke.h> // __invoke
39#include <bits/stl_construct.h> // construct_at
40#include <bits/utility.h> // in_place_t
41
42namespace std _GLIBCXX_VISIBILITY(default)
43{
44_GLIBCXX_BEGIN_NAMESPACE_VERSION
45
46 /**
47 * @defgroup expected_values Expected values
48 * @addtogroup utilities
49 * @since C++23
50 * @{
51 */
52
53#define __cpp_lib_expected 202211L
54
55 /// Discriminated union that holds an expected value or an error value.
56 /**
57 * @since C++23
58 */
59 template<typename _Tp, typename _Er>
60 class expected;
61
62 /// Wrapper type used to pass an error value to a `std::expected`.
63 /**
64 * @since C++23
65 */
66 template<typename _Er>
67 class unexpected;
68
69 /// Exception thrown by std::expected when the value() is not present.
70 /**
71 * @since C++23
72 */
73 template<typename _Er>
74 class bad_expected_access;
75
76 template<>
77 class bad_expected_access<void> : public exception
78 {
79 protected:
80 bad_expected_access() noexcept { }
81 bad_expected_access(const bad_expected_access&) = default;
82 bad_expected_access(bad_expected_access&&) = default;
83 bad_expected_access& operator=(const bad_expected_access&) = default;
84 bad_expected_access& operator=(bad_expected_access&&) = default;
85 ~bad_expected_access() = default;
86
87 public:
88
89 [[nodiscard]]
90 const char*
91 what() const noexcept override
92 { return "bad access to std::expected without expected value"; }
93 };
94
95 template<typename _Er>
96 class bad_expected_access : public bad_expected_access<void> {
97 public:
98 explicit
99 bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
100
101 // XXX const char* what() const noexcept override;
102
103 [[nodiscard]]
104 _Er&
105 error() & noexcept
106 { return _M_unex; }
107
108 [[nodiscard]]
109 const _Er&
110 error() const & noexcept
111 { return _M_unex; }
112
113 [[nodiscard]]
114 _Er&&
115 error() && noexcept
116 { return std::move(_M_unex); }
117
118 [[nodiscard]]
119 const _Er&&
120 error() const && noexcept
121 { return std::move(_M_unex); }
122
123 private:
124 _Er _M_unex;
125 };
126
127 /// Tag type for constructing unexpected values in a std::expected
128 /**
129 * @since C++23
130 */
131 struct unexpect_t
132 {
133 explicit unexpect_t() = default;
134 };
135
136 /// Tag for constructing unexpected values in a std::expected
137 /**
138 * @since C++23
139 */
140 inline constexpr unexpect_t unexpect{};
141
142/// @cond undoc
143namespace __expected
144{
145 template<typename _Tp>
146 constexpr bool __is_expected = false;
147 template<typename _Tp, typename _Er>
148 constexpr bool __is_expected<expected<_Tp, _Er>> = true;
149
150 template<typename _Tp>
151 constexpr bool __is_unexpected = false;
152 template<typename _Tp>
153 constexpr bool __is_unexpected<unexpected<_Tp>> = true;
154
155 template<typename _Fn, typename _Tp>
156 using __result = remove_cvref_t<invoke_result_t<_Fn&&, _Tp&&>>;
157 template<typename _Fn, typename _Tp>
158 using __result_xform = remove_cv_t<invoke_result_t<_Fn&&, _Tp&&>>;
159 template<typename _Fn>
160 using __result0 = remove_cvref_t<invoke_result_t<_Fn&&>>;
161 template<typename _Fn>
162 using __result0_xform = remove_cv_t<invoke_result_t<_Fn&&>>;
163
164 template<typename _Er>
165 concept __can_be_unexpected
166 = is_object_v<_Er> && (!is_array_v<_Er>)
167 && (!__expected::__is_unexpected<_Er>)
168 && (!is_const_v<_Er>) && (!is_volatile_v<_Er>);
169
170 // Tag types for in-place construction from an invocation result.
171 struct __in_place_inv { };
172 struct __unexpect_inv { };
173}
174/// @endcond
175
176 template<typename _Er>
177 class unexpected
178 {
179 static_assert( __expected::__can_be_unexpected<_Er> );
180
181 public:
182 constexpr unexpected(const unexpected&) = default;
183 constexpr unexpected(unexpected&&) = default;
184
185 template<typename _Err = _Er>
186 requires (!is_same_v<remove_cvref_t<_Err>, unexpected>)
187 && (!is_same_v<remove_cvref_t<_Err>, in_place_t>)
188 && is_constructible_v<_Er, _Err>
189 constexpr explicit
190 unexpected(_Err&& __e)
191 noexcept(is_nothrow_constructible_v<_Er, _Err>)
192 : _M_unex(std::forward<_Err>(__e))
193 { }
194
195 template<typename... _Args>
196 requires is_constructible_v<_Er, _Args...>
197 constexpr explicit
198 unexpected(in_place_t, _Args&&... __args)
199 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
200 : _M_unex(std::forward<_Args>(__args)...)
201 { }
202
203 template<typename _Up, typename... _Args>
204 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
205 constexpr explicit
206 unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
207 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
208 _Args...>)
209 : _M_unex(__il, std::forward<_Args>(__args)...)
210 { }
211
212 constexpr unexpected& operator=(const unexpected&) = default;
213 constexpr unexpected& operator=(unexpected&&) = default;
214
215
216 [[nodiscard]]
217 constexpr const _Er&
218 error() const & noexcept { return _M_unex; }
219
220 [[nodiscard]]
221 constexpr _Er&
222 error() & noexcept { return _M_unex; }
223
224 [[nodiscard]]
225 constexpr const _Er&&
226 error() const && noexcept { return std::move(_M_unex); }
227
228 [[nodiscard]]
229 constexpr _Er&&
230 error() && noexcept { return std::move(_M_unex); }
231
232 constexpr void
233 swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>)
234 requires is_swappable_v<_Er>
235 {
236 using std::swap;
237 swap(_M_unex, __other._M_unex);
238 }
239
240 template<typename _Err>
241 [[nodiscard]]
242 friend constexpr bool
243 operator==(const unexpected& __x, const unexpected<_Err>& __y)
244 { return __x._M_unex == __y.error(); }
245
246 friend constexpr void
247 swap(unexpected& __x, unexpected& __y) noexcept(noexcept(__x.swap(__y)))
248 requires is_swappable_v<_Er>
249 { __x.swap(__y); }
250
251 private:
252 _Er _M_unex;
253 };
254
255 template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
256
257/// @cond undoc
258namespace __expected
259{
260 template<typename _Tp>
261 struct _Guard
262 {
263 static_assert( is_nothrow_move_constructible_v<_Tp> );
264
265 constexpr explicit
266 _Guard(_Tp& __x)
267 : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
268 { std::destroy_at(_M_guarded); }
269
270 constexpr
271 ~_Guard()
272 {
273 if (_M_guarded) [[unlikely]]
274 std::construct_at(_M_guarded, std::move(_M_tmp));
275 }
276
277 _Guard(const _Guard&) = delete;
278 _Guard& operator=(const _Guard&) = delete;
279
280 constexpr _Tp&&
281 release() noexcept
282 {
283 _M_guarded = nullptr;
284 return std::move(_M_tmp);
285 }
286
287 private:
288 _Tp* _M_guarded;
289 _Tp _M_tmp;
290 };
291
292 // reinit-expected helper from [expected.object.assign]
293 template<typename _Tp, typename _Up, typename _Vp>
294 constexpr void
295 __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
296 noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
297 {
298 if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
299 {
300 std::destroy_at(__oldval);
301 std::construct_at(__newval, std::forward<_Vp>(__arg));
302 }
303 else if constexpr (is_nothrow_move_constructible_v<_Tp>)
304 {
305 _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
306 std::destroy_at(__oldval);
307 std::construct_at(__newval, std::move(__tmp));
308 }
309 else
310 {
311 _Guard<_Up> __guard(*__oldval);
312 std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
313 __guard.release();
314 }
315 }
316}
317/// @endcond
318
319 template<typename _Tp, typename _Er>
320 class expected
321 {
322 static_assert( ! is_reference_v<_Tp> );
323 static_assert( ! is_function_v<_Tp> );
324 static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
325 static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
326 static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
327 static_assert( __expected::__can_be_unexpected<_Er> );
328
329 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
330 static constexpr bool __cons_from_expected
331 = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
332 is_constructible<_Tp, expected<_Up, _Err>>,
333 is_constructible<_Tp, const expected<_Up, _Err>&>,
334 is_constructible<_Tp, const expected<_Up, _Err>>,
335 is_convertible<expected<_Up, _Err>&, _Tp>,
336 is_convertible<expected<_Up, _Err>, _Tp>,
337 is_convertible<const expected<_Up, _Err>&, _Tp>,
338 is_convertible<const expected<_Up, _Err>, _Tp>,
339 is_constructible<_Unex, expected<_Up, _Err>&>,
340 is_constructible<_Unex, expected<_Up, _Err>>,
341 is_constructible<_Unex, const expected<_Up, _Err>&>,
342 is_constructible<_Unex, const expected<_Up, _Err>>
343 >;
344
345 template<typename _Up, typename _Err>
346 constexpr static bool __explicit_conv
347 = __or_v<__not_<is_convertible<_Up, _Tp>>,
348 __not_<is_convertible<_Err, _Er>>
349 >;
350
351 template<typename _Up>
352 static constexpr bool __same_val
353 = is_same_v<typename _Up::value_type, _Tp>;
354
355 template<typename _Up>
356 static constexpr bool __same_err
357 = is_same_v<typename _Up::error_type, _Er>;
358
359 public:
360 using value_type = _Tp;
361 using error_type = _Er;
362 using unexpected_type = unexpected<_Er>;
363
364 template<typename _Up>
365 using rebind = expected<_Up, error_type>;
366
367 constexpr
368 expected()
369 noexcept(is_nothrow_default_constructible_v<_Tp>)
370 requires is_default_constructible_v<_Tp>
371 : _M_val(), _M_has_value(true)
372 { }
373
374 expected(const expected&) = default;
375
376 constexpr
377 expected(const expected& __x)
378 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
379 is_nothrow_copy_constructible<_Er>>)
380 requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
381 && (!is_trivially_copy_constructible_v<_Tp>
382 || !is_trivially_copy_constructible_v<_Er>)
383 : _M_has_value(__x._M_has_value)
384 {
385 if (_M_has_value)
386 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
387 else
388 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
389 }
390
391 expected(expected&&) = default;
392
393 constexpr
394 expected(expected&& __x)
395 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
396 is_nothrow_move_constructible<_Er>>)
397 requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
398 && (!is_trivially_move_constructible_v<_Tp>
399 || !is_trivially_move_constructible_v<_Er>)
400 : _M_has_value(__x._M_has_value)
401 {
402 if (_M_has_value)
403 std::construct_at(__builtin_addressof(_M_val),
404 std::move(__x)._M_val);
405 else
406 std::construct_at(__builtin_addressof(_M_unex),
407 std::move(__x)._M_unex);
408 }
409
410 template<typename _Up, typename _Gr>
411 requires is_constructible_v<_Tp, const _Up&>
412 && is_constructible_v<_Er, const _Gr&>
413 && (!__cons_from_expected<_Up, _Gr>)
414 constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
415 expected(const expected<_Up, _Gr>& __x)
416 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
417 is_nothrow_constructible<_Er, const _Gr&>>)
418 : _M_has_value(__x._M_has_value)
419 {
420 if (_M_has_value)
421 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
422 else
423 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
424 }
425
426 template<typename _Up, typename _Gr>
427 requires is_constructible_v<_Tp, _Up>
428 && is_constructible_v<_Er, _Gr>
429 && (!__cons_from_expected<_Up, _Gr>)
430 constexpr explicit(__explicit_conv<_Up, _Gr>)
431 expected(expected<_Up, _Gr>&& __x)
432 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
433 is_nothrow_constructible<_Er, _Gr>>)
434 : _M_has_value(__x._M_has_value)
435 {
436 if (_M_has_value)
437 std::construct_at(__builtin_addressof(_M_val),
438 std::move(__x)._M_val);
439 else
440 std::construct_at(__builtin_addressof(_M_unex),
441 std::move(__x)._M_unex);
442 }
443
444 template<typename _Up = _Tp>
445 requires (!is_same_v<remove_cvref_t<_Up>, expected>)
446 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
447 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
448 && is_constructible_v<_Tp, _Up>
449 constexpr explicit(!is_convertible_v<_Up, _Tp>)
450 expected(_Up&& __v)
451 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
452 : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
453 { }
454
455 template<typename _Gr = _Er>
456 requires is_constructible_v<_Er, const _Gr&>
457 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
458 expected(const unexpected<_Gr>& __u)
459 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
460 : _M_unex(__u.error()), _M_has_value(false)
461 { }
462
463 template<typename _Gr = _Er>
464 requires is_constructible_v<_Er, _Gr>
465 constexpr explicit(!is_convertible_v<_Gr, _Er>)
466 expected(unexpected<_Gr>&& __u)
467 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
468 : _M_unex(std::move(__u).error()), _M_has_value(false)
469 { }
470
471 template<typename... _Args>
472 requires is_constructible_v<_Tp, _Args...>
473 constexpr explicit
474 expected(in_place_t, _Args&&... __args)
475 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
476 : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
477 { }
478
479 template<typename _Up, typename... _Args>
480 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
481 constexpr explicit
482 expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
483 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
484 _Args...>)
485 : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
486 { }
487
488 template<typename... _Args>
489 requires is_constructible_v<_Er, _Args...>
490 constexpr explicit
491 expected(unexpect_t, _Args&&... __args)
492 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
493 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
494 { }
495
496 template<typename _Up, typename... _Args>
497 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
498 constexpr explicit
499 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
500 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
501 _Args...>)
502 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
503 { }
504
505 constexpr ~expected() = default;
506
507 constexpr ~expected()
508 requires (!is_trivially_destructible_v<_Tp>)
509 || (!is_trivially_destructible_v<_Er>)
510 {
511 if (_M_has_value)
512 std::destroy_at(__builtin_addressof(_M_val));
513 else
514 std::destroy_at(__builtin_addressof(_M_unex));
515 }
516
517 // assignment
518
519 expected& operator=(const expected&) = delete;
520
521 constexpr expected&
522 operator=(const expected& __x)
523 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
524 is_nothrow_copy_constructible<_Er>,
525 is_nothrow_copy_assignable<_Tp>,
526 is_nothrow_copy_assignable<_Er>>)
527 requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
528 && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
529 && (is_nothrow_move_constructible_v<_Tp>
530 || is_nothrow_move_constructible_v<_Er>)
531 {
532 if (__x._M_has_value)
533 this->_M_assign_val(__x._M_val);
534 else
535 this->_M_assign_unex(__x._M_unex);
536 return *this;
537 }
538
539 constexpr expected&
540 operator=(expected&& __x)
541 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
542 is_nothrow_move_constructible<_Er>,
543 is_nothrow_move_assignable<_Tp>,
544 is_nothrow_move_assignable<_Er>>)
545 requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
546 && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
547 && (is_nothrow_move_constructible_v<_Tp>
548 || is_nothrow_move_constructible_v<_Er>)
549 {
550 if (__x._M_has_value)
551 _M_assign_val(std::move(__x._M_val));
552 else
553 _M_assign_unex(std::move(__x._M_unex));
554 return *this;
555 }
556
557 template<typename _Up = _Tp>
558 requires (!is_same_v<expected, remove_cvref_t<_Up>>)
559 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
560 && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
561 && (is_nothrow_constructible_v<_Tp, _Up>
562 || is_nothrow_move_constructible_v<_Tp>
563 || is_nothrow_move_constructible_v<_Er>)
564 constexpr expected&
565 operator=(_Up&& __v)
566 {
567 _M_assign_val(std::forward<_Up>(__v));
568 return *this;
569 }
570
571 template<typename _Gr>
572 requires is_constructible_v<_Er, const _Gr&>
573 && is_assignable_v<_Er&, const _Gr&>
574 && (is_nothrow_constructible_v<_Er, const _Gr&>
575 || is_nothrow_move_constructible_v<_Tp>
576 || is_nothrow_move_constructible_v<_Er>)
577 constexpr expected&
578 operator=(const unexpected<_Gr>& __e)
579 {
580 _M_assign_unex(__e.error());
581 return *this;
582 }
583
584 template<typename _Gr>
585 requires is_constructible_v<_Er, _Gr>
586 && is_assignable_v<_Er&, _Gr>
587 && (is_nothrow_constructible_v<_Er, _Gr>
588 || is_nothrow_move_constructible_v<_Tp>
589 || is_nothrow_move_constructible_v<_Er>)
590 constexpr expected&
591 operator=(unexpected<_Gr>&& __e)
592 {
593 _M_assign_unex(std::move(__e).error());
594 return *this;
595 }
596
597 // modifiers
598
599 template<typename... _Args>
600 requires is_nothrow_constructible_v<_Tp, _Args...>
601 constexpr _Tp&
602 emplace(_Args&&... __args) noexcept
603 {
604 if (_M_has_value)
605 std::destroy_at(__builtin_addressof(_M_val));
606 else
607 {
608 std::destroy_at(__builtin_addressof(_M_unex));
609 _M_has_value = true;
610 }
611 std::construct_at(__builtin_addressof(_M_val),
612 std::forward<_Args>(__args)...);
613 return _M_val;
614 }
615
616 template<typename _Up, typename... _Args>
617 requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
618 _Args...>
619 constexpr _Tp&
620 emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
621 {
622 if (_M_has_value)
623 std::destroy_at(__builtin_addressof(_M_val));
624 else
625 {
626 std::destroy_at(__builtin_addressof(_M_unex));
627 _M_has_value = true;
628 }
629 std::construct_at(__builtin_addressof(_M_val),
630 __il, std::forward<_Args>(__args)...);
631 return _M_val;
632 }
633
634 // swap
635 constexpr void
636 swap(expected& __x)
637 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
638 is_nothrow_move_constructible<_Er>,
639 is_nothrow_swappable<_Tp&>,
640 is_nothrow_swappable<_Er&>>)
641 requires is_swappable_v<_Tp> && is_swappable_v<_Er>
642 && is_move_constructible_v<_Tp>
643 && is_move_constructible_v<_Er>
644 && (is_nothrow_move_constructible_v<_Tp>
645 || is_nothrow_move_constructible_v<_Er>)
646 {
647 if (_M_has_value)
648 {
649 if (__x._M_has_value)
650 {
651 using std::swap;
652 swap(_M_val, __x._M_val);
653 }
654 else
655 this->_M_swap_val_unex(__x);
656 }
657 else
658 {
659 if (__x._M_has_value)
660 __x._M_swap_val_unex(*this);
661 else
662 {
663 using std::swap;
664 swap(_M_unex, __x._M_unex);
665 }
666 }
667 }
668
669 // observers
670
671 [[nodiscard]]
672 constexpr const _Tp*
673 operator->() const noexcept
674 {
675 __glibcxx_assert(_M_has_value);
676 return __builtin_addressof(_M_val);
677 }
678
679 [[nodiscard]]
680 constexpr _Tp*
681 operator->() noexcept
682 {
683 __glibcxx_assert(_M_has_value);
684 return __builtin_addressof(_M_val);
685 }
686
687 [[nodiscard]]
688 constexpr const _Tp&
689 operator*() const & noexcept
690 {
691 __glibcxx_assert(_M_has_value);
692 return _M_val;
693 }
694
695 [[nodiscard]]
696 constexpr _Tp&
697 operator*() & noexcept
698 {
699 __glibcxx_assert(_M_has_value);
700 return _M_val;
701 }
702
703 [[nodiscard]]
704 constexpr const _Tp&&
705 operator*() const && noexcept
706 {
707 __glibcxx_assert(_M_has_value);
708 return std::move(_M_val);
709 }
710
711 [[nodiscard]]
712 constexpr _Tp&&
713 operator*() && noexcept
714 {
715 __glibcxx_assert(_M_has_value);
716 return std::move(_M_val);
717 }
718
719 [[nodiscard]]
720 constexpr explicit
721 operator bool() const noexcept { return _M_has_value; }
722
723 [[nodiscard]]
724 constexpr bool has_value() const noexcept { return _M_has_value; }
725
726 constexpr const _Tp&
727 value() const &
728 {
729 if (_M_has_value) [[likely]]
730 return _M_val;
731 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
732 }
733
734 constexpr _Tp&
735 value() &
736 {
737 if (_M_has_value) [[likely]]
738 return _M_val;
739 const auto& __unex = _M_unex;
740 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__unex));
741 }
742
743 constexpr const _Tp&&
744 value() const &&
745 {
746 if (_M_has_value) [[likely]]
747 return std::move(_M_val);
748 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
749 std::move(_M_unex)));
750 }
751
752 constexpr _Tp&&
753 value() &&
754 {
755 if (_M_has_value) [[likely]]
756 return std::move(_M_val);
757 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
758 std::move(_M_unex)));
759 }
760
761 constexpr const _Er&
762 error() const & noexcept
763 {
764 __glibcxx_assert(!_M_has_value);
765 return _M_unex;
766 }
767
768 constexpr _Er&
769 error() & noexcept
770 {
771 __glibcxx_assert(!_M_has_value);
772 return _M_unex;
773 }
774
775 constexpr const _Er&&
776 error() const && noexcept
777 {
778 __glibcxx_assert(!_M_has_value);
779 return std::move(_M_unex);
780 }
781
782 constexpr _Er&&
783 error() && noexcept
784 {
785 __glibcxx_assert(!_M_has_value);
786 return std::move(_M_unex);
787 }
788
789 template<typename _Up>
790 constexpr _Tp
791 value_or(_Up&& __v) const &
792 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
793 is_nothrow_convertible<_Up, _Tp>>)
794 {
795 static_assert( is_copy_constructible_v<_Tp> );
796 static_assert( is_convertible_v<_Up, _Tp> );
797
798 if (_M_has_value)
799 return _M_val;
800 return static_cast<_Tp>(std::forward<_Up>(__v));
801 }
802
803 template<typename _Up>
804 constexpr _Tp
805 value_or(_Up&& __v) &&
806 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
807 is_nothrow_convertible<_Up, _Tp>>)
808 {
809 static_assert( is_move_constructible_v<_Tp> );
810 static_assert( is_convertible_v<_Up, _Tp> );
811
812 if (_M_has_value)
813 return std::move(_M_val);
814 return static_cast<_Tp>(std::forward<_Up>(__v));
815 }
816
817 template<typename _Gr = _Er>
818 constexpr _Er
819 error_or(_Gr&& __e) const&
820 {
821 static_assert( is_copy_constructible_v<_Er> );
822 static_assert( is_convertible_v<_Gr, _Er> );
823
824 if (_M_has_value)
825 return std::forward<_Gr>(__e);
826 return _M_unex;
827 }
828
829 template<typename _Gr = _Er>
830 constexpr _Er
831 error_or(_Gr&& __e) &&
832 {
833 static_assert( is_move_constructible_v<_Er> );
834 static_assert( is_convertible_v<_Gr, _Er> );
835
836 if (_M_has_value)
837 return std::forward<_Gr>(__e);
838 return std::move(_M_unex);
839 }
840
841 // monadic operations
842
843 template<typename _Fn> requires is_copy_constructible_v<_Er>
844 constexpr auto
845 and_then(_Fn&& __f) &
846 {
847 using _Up = __expected::__result<_Fn, _Tp&>;
848 static_assert(__expected::__is_expected<_Up>);
849 static_assert(is_same_v<typename _Up::error_type, _Er>);
850
851 if (has_value())
852 return std::__invoke(std::forward<_Fn>(__f), value());
853 else
854 return _Up(unexpect, error());
855 }
856
857 template<typename _Fn> requires is_copy_constructible_v<_Er>
858 constexpr auto
859 and_then(_Fn&& __f) const &
860 {
861 using _Up = __expected::__result<_Fn, const _Tp&>;
862 static_assert(__expected::__is_expected<_Up>);
863 static_assert(is_same_v<typename _Up::error_type, _Er>);
864
865 if (has_value())
866 return std::__invoke(std::forward<_Fn>(__f), value());
867 else
868 return _Up(unexpect, error());
869 }
870
871 template<typename _Fn> requires is_move_constructible_v<_Er>
872 constexpr auto
873 and_then(_Fn&& __f) &&
874 {
875 using _Up = __expected::__result<_Fn, _Tp&&>;
876 static_assert(__expected::__is_expected<_Up>);
877 static_assert(is_same_v<typename _Up::error_type, _Er>);
878
879 if (has_value())
880 return std::__invoke(std::forward<_Fn>(__f), std::move(value()));
881 else
882 return _Up(unexpect, std::move(error()));
883 }
884
885
886 template<typename _Fn> requires is_move_constructible_v<_Er>
887 constexpr auto
888 and_then(_Fn&& __f) const &&
889 {
890 using _Up = __expected::__result<_Fn, const _Tp&&>;
891 static_assert(__expected::__is_expected<_Up>);
892 static_assert(is_same_v<typename _Up::error_type, _Er>);
893
894 if (has_value())
895 return std::__invoke(std::forward<_Fn>(__f), std::move(value()));
896 else
897 return _Up(unexpect, std::move(error()));
898 }
899
900 template<typename _Fn> requires is_copy_constructible_v<_Er>
901 constexpr auto
902 or_else(_Fn&& __f) &
903 {
904 using _Gr = __expected::__result<_Fn, _Er&>;
905 static_assert(__expected::__is_expected<_Gr>);
906 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
907
908 if (has_value())
909 return _Gr(in_place, value());
910 else
911 return std::__invoke(std::forward<_Fn>(__f), error());
912 }
913
914 template<typename _Fn> requires is_copy_constructible_v<_Er>
915 constexpr auto
916 or_else(_Fn&& __f) const &
917 {
918 using _Gr = __expected::__result<_Fn, const _Er&>;
919 static_assert(__expected::__is_expected<_Gr>);
920 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
921
922 if (has_value())
923 return _Gr(in_place, value());
924 else
925 return std::__invoke(std::forward<_Fn>(__f), error());
926 }
927
928
929 template<typename _Fn> requires is_move_constructible_v<_Er>
930 constexpr auto
931 or_else(_Fn&& __f) &&
932 {
933 using _Gr = __expected::__result<_Fn, _Er&&>;
934 static_assert(__expected::__is_expected<_Gr>);
935 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
936
937 if (has_value())
938 return _Gr(in_place, std::move(value()));
939 else
940 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
941 }
942
943 template<typename _Fn> requires is_move_constructible_v<_Er>
944 constexpr auto
945 or_else(_Fn&& __f) const &&
946 {
947 using _Gr = __expected::__result<_Fn, const _Er&&>;
948 static_assert(__expected::__is_expected<_Gr>);
949 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
950
951 if (has_value())
952 return _Gr(in_place, std::move(value()));
953 else
954 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
955 }
956
957 template<typename _Fn> requires is_copy_constructible_v<_Er>
958 constexpr auto
959 transform(_Fn&& __f) &
960 {
961 using _Up = __expected::__result_xform<_Fn, _Tp&>;
962 using _Res = expected<_Up, _Er>;
963
964 if (has_value())
965 return _Res(__in_place_inv{}, [&]() {
966 return std::__invoke(std::forward<_Fn>(__f),
967 _M_val);
968 });
969 else
970 return _Res(unexpect, std::move(error()));
971 }
972
973 template<typename _Fn> requires is_copy_constructible_v<_Er>
974 constexpr auto
975 transform(_Fn&& __f) const &
976 {
977 using _Up = __expected::__result_xform<_Fn, const _Tp&>;
978 using _Res = expected<_Up, _Er>;
979
980 if (has_value())
981 return _Res(__in_place_inv{}, [&]() {
982 return std::__invoke(std::forward<_Fn>(__f),
983 _M_val);
984 });
985 else
986 return _Res(unexpect, std::move(error()));
987 }
988
989 template<typename _Fn> requires is_move_constructible_v<_Er>
990 constexpr auto
991 transform(_Fn&& __f) &&
992 {
993 using _Up = __expected::__result_xform<_Fn, _Tp>;
994 using _Res = expected<_Up, _Er>;
995
996 if (has_value())
997 return _Res(__in_place_inv{}, [&]() {
998 return std::__invoke(std::forward<_Fn>(__f),
999 std::move(_M_val));
1000 });
1001 else
1002 return _Res(unexpect, std::move(error()));
1003 }
1004
1005 template<typename _Fn> requires is_move_constructible_v<_Er>
1006 constexpr auto
1007 transform(_Fn&& __f) const &&
1008 {
1009 using _Up = __expected::__result_xform<_Fn, const _Tp>;
1010 using _Res = expected<_Up, _Er>;
1011
1012 if (has_value())
1013 return _Res(__in_place_inv{}, [&]() {
1014 return std::__invoke(std::forward<_Fn>(__f),
1015 std::move(_M_val));
1016 });
1017 else
1018 return _Res(unexpect, std::move(error()));
1019 }
1020
1021 template<typename _Fn> requires is_copy_constructible_v<_Tp>
1022 constexpr auto
1023 transform_error(_Fn&& __f) &
1024 {
1025 using _Gr = __expected::__result_xform<_Fn, _Er&>;
1026 using _Res = expected<_Tp, _Gr>;
1027
1028 if (has_value())
1029 return _Res(in_place, value());
1030 else
1031 return _Res(__unexpect_inv{}, [&]() {
1032 return std::__invoke(std::forward<_Fn>(__f),
1033 _M_unex);
1034 });
1035 }
1036
1037 template<typename _Fn> requires is_copy_constructible_v<_Tp>
1038 constexpr auto
1039 transform_error(_Fn&& __f) const &
1040 {
1041 using _Gr = __expected::__result_xform<_Fn, const _Er&>;
1042 using _Res = expected<_Tp, _Gr>;
1043
1044 if (has_value())
1045 return _Res(in_place, value());
1046 else
1047 return _Res(__unexpect_inv{}, [&]() {
1048 return std::__invoke(std::forward<_Fn>(__f),
1049 _M_unex);
1050 });
1051 }
1052
1053 template<typename _Fn> requires is_move_constructible_v<_Tp>
1054 constexpr auto
1055 transform_error(_Fn&& __f) &&
1056 {
1057 using _Gr = __expected::__result_xform<_Fn, _Er&&>;
1058 using _Res = expected<_Tp, _Gr>;
1059
1060 if (has_value())
1061 return _Res(in_place, std::move(value()));
1062 else
1063 return _Res(__unexpect_inv{}, [&]() {
1064 return std::__invoke(std::forward<_Fn>(__f),
1065 std::move(_M_unex));
1066 });
1067 }
1068
1069 template<typename _Fn> requires is_move_constructible_v<_Tp>
1070 constexpr auto
1071 transform_error(_Fn&& __f) const &&
1072 {
1073 using _Gr = __expected::__result_xform<_Fn, const _Er&&>;
1074 using _Res = expected<_Tp, _Gr>;
1075
1076 if (has_value())
1077 return _Res(in_place, std::move(value()));
1078 else
1079 return _Res(__unexpect_inv{}, [&]() {
1080 return std::__invoke(std::forward<_Fn>(__f),
1081 std::move(_M_unex));
1082 });
1083 }
1084
1085 // equality operators
1086
1087 template<typename _Up, typename _Er2>
1088 requires (!is_void_v<_Up>)
1089 friend constexpr bool
1090 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1091 // FIXME: noexcept(noexcept(bool(*__x == *__y))
1092 // && noexcept(bool(__x.error() == __y.error())))
1093 {
1094 if (__x.has_value())
1095 return __y.has_value() && bool(*__x == *__y);
1096 else
1097 return !__y.has_value() && bool(__x.error() == __y.error());
1098 }
1099
1100 template<typename _Up>
1101 friend constexpr bool
1102 operator==(const expected& __x, const _Up& __v)
1103 // FIXME: noexcept(noexcept(bool(*__x == __v)))
1104 { return __x.has_value() && bool(*__x == __v); }
1105
1106 template<typename _Er2>
1107 friend constexpr bool
1108 operator==(const expected& __x, const unexpected<_Er2>& __e)
1109 // FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
1110 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1111
1112 friend constexpr void
1113 swap(expected& __x, expected& __y)
1114 noexcept(noexcept(__x.swap(__y)))
1115 requires requires {__x.swap(__y);}
1116 { __x.swap(__y); }
1117
1118 private:
1119 template<typename, typename> friend class expected;
1120
1121 template<typename _Vp>
1122 constexpr void
1123 _M_assign_val(_Vp&& __v)
1124 {
1125 if (_M_has_value)
1126 _M_val = std::forward<_Vp>(__v);
1127 else
1128 {
1129 __expected::__reinit(__builtin_addressof(_M_val),
1130 __builtin_addressof(_M_unex),
1131 std::forward<_Vp>(__v));
1132 _M_has_value = true;
1133 }
1134 }
1135
1136 template<typename _Vp>
1137 constexpr void
1138 _M_assign_unex(_Vp&& __v)
1139 {
1140 if (_M_has_value)
1141 {
1142 __expected::__reinit(__builtin_addressof(_M_unex),
1143 __builtin_addressof(_M_val),
1144 std::forward<_Vp>(__v));
1145 _M_has_value = false;
1146 }
1147 else
1148 _M_unex = std::forward<_Vp>(__v);
1149 }
1150
1151 // Swap two expected objects when only one has a value.
1152 // Precondition: this->_M_has_value && !__rhs._M_has_value
1153 constexpr void
1154 _M_swap_val_unex(expected& __rhs)
1155 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1156 is_nothrow_move_constructible<_Tp>>)
1157 {
1158 if constexpr (is_nothrow_move_constructible_v<_Er>)
1159 {
1160 __expected::_Guard<_Er> __guard(__rhs._M_unex);
1161 std::construct_at(__builtin_addressof(__rhs._M_val),
1162 std::move(_M_val)); // might throw
1163 __rhs._M_has_value = true;
1164 std::destroy_at(__builtin_addressof(_M_val));
1165 std::construct_at(__builtin_addressof(_M_unex),
1166 __guard.release());
1167 _M_has_value = false;
1168 }
1169 else
1170 {
1171 __expected::_Guard<_Tp> __guard(_M_val);
1172 std::construct_at(__builtin_addressof(_M_unex),
1173 std::move(__rhs._M_unex)); // might throw
1174 _M_has_value = false;
1175 std::destroy_at(__builtin_addressof(__rhs._M_unex));
1176 std::construct_at(__builtin_addressof(__rhs._M_val),
1177 __guard.release());
1178 __rhs._M_has_value = true;
1179 }
1180 }
1181
1182 using __in_place_inv = __expected::__in_place_inv;
1183 using __unexpect_inv = __expected::__unexpect_inv;
1184
1185 template<typename _Fn>
1186 explicit constexpr
1187 expected(__in_place_inv, _Fn&& __fn)
1188 : _M_val(std::forward<_Fn>(__fn)()), _M_has_value(true)
1189 { }
1190
1191 template<typename _Fn>
1192 explicit constexpr
1193 expected(__unexpect_inv, _Fn&& __fn)
1194 : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
1195 { }
1196
1197 union {
1198 _Tp _M_val;
1199 _Er _M_unex;
1200 };
1201
1202 bool _M_has_value;
1203 };
1204
1205 // Partial specialization for std::expected<cv void, E>
1206 template<typename _Tp, typename _Er> requires is_void_v<_Tp>
1207 class expected<_Tp, _Er>
1208 {
1209 static_assert( __expected::__can_be_unexpected<_Er> );
1210
1211 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
1212 static constexpr bool __cons_from_expected
1213 = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
1214 is_constructible<_Unex, expected<_Up, _Err>>,
1215 is_constructible<_Unex, const expected<_Up, _Err>&>,
1216 is_constructible<_Unex, const expected<_Up, _Err>>
1217 >;
1218
1219 template<typename _Up>
1220 static constexpr bool __same_val
1221 = is_same_v<typename _Up::value_type, _Tp>;
1222
1223 template<typename _Up>
1224 static constexpr bool __same_err
1225 = is_same_v<typename _Up::error_type, _Er>;
1226
1227 public:
1228 using value_type = _Tp;
1229 using error_type = _Er;
1230 using unexpected_type = unexpected<_Er>;
1231
1232 template<typename _Up>
1233 using rebind = expected<_Up, error_type>;
1234
1235 constexpr
1236 expected() noexcept
1237 : _M_void(), _M_has_value(true)
1238 { }
1239
1240 expected(const expected&) = default;
1241
1242 constexpr
1243 expected(const expected& __x)
1244 noexcept(is_nothrow_copy_constructible_v<_Er>)
1245 requires is_copy_constructible_v<_Er>
1246 && (!is_trivially_copy_constructible_v<_Er>)
1247 : _M_void(), _M_has_value(__x._M_has_value)
1248 {
1249 if (!_M_has_value)
1250 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
1251 }
1252
1253 expected(expected&&) = default;
1254
1255 constexpr
1256 expected(expected&& __x)
1257 noexcept(is_nothrow_move_constructible_v<_Er>)
1258 requires is_move_constructible_v<_Er>
1259 && (!is_trivially_move_constructible_v<_Er>)
1260 : _M_void(), _M_has_value(__x._M_has_value)
1261 {
1262 if (!_M_has_value)
1263 std::construct_at(__builtin_addressof(_M_unex),
1264 std::move(__x)._M_unex);
1265 }
1266
1267 template<typename _Up, typename _Gr>
1268 requires is_void_v<_Up>
1269 && is_constructible_v<_Er, const _Gr&>
1270 && (!__cons_from_expected<_Up, _Gr>)
1271 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
1272 expected(const expected<_Up, _Gr>& __x)
1273 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
1274 : _M_void(), _M_has_value(__x._M_has_value)
1275 {
1276 if (!_M_has_value)
1277 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
1278 }
1279
1280 template<typename _Up, typename _Gr>
1281 requires is_void_v<_Up>
1282 && is_constructible_v<_Er, _Gr>
1283 && (!__cons_from_expected<_Up, _Gr>)
1284 constexpr explicit(!is_convertible_v<_Gr, _Er>)
1285 expected(expected<_Up, _Gr>&& __x)
1286 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
1287 : _M_void(), _M_has_value(__x._M_has_value)
1288 {
1289 if (!_M_has_value)
1290 std::construct_at(__builtin_addressof(_M_unex),
1291 std::move(__x)._M_unex);
1292 }
1293
1294 template<typename _Gr = _Er>
1295 requires is_constructible_v<_Er, const _Gr&>
1296 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
1297 expected(const unexpected<_Gr>& __u)
1298 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
1299 : _M_unex(__u.error()), _M_has_value(false)
1300 { }
1301
1302 template<typename _Gr = _Er>
1303 requires is_constructible_v<_Er, _Gr>
1304 constexpr explicit(!is_convertible_v<_Gr, _Er>)
1305 expected(unexpected<_Gr>&& __u)
1306 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
1307 : _M_unex(std::move(__u).error()), _M_has_value(false)
1308 { }
1309
1310 constexpr explicit
1311 expected(in_place_t) noexcept
1312 : expected()
1313 { }
1314
1315 template<typename... _Args>
1316 requires is_constructible_v<_Er, _Args...>
1317 constexpr explicit
1318 expected(unexpect_t, _Args&&... __args)
1319 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1320 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1321 { }
1322
1323 template<typename _Up, typename... _Args>
1324 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1325 constexpr explicit
1326 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1327 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1328 _Args...>)
1329 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1330 { }
1331
1332 constexpr ~expected() = default;
1333
1334 constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1335 {
1336 if (!_M_has_value)
1337 std::destroy_at(__builtin_addressof(_M_unex));
1338 }
1339
1340 // assignment
1341
1342 expected& operator=(const expected&) = delete;
1343
1344 constexpr expected&
1345 operator=(const expected& __x)
1346 noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1347 is_nothrow_copy_assignable<_Er>>)
1348 requires is_copy_constructible_v<_Er>
1349 && is_copy_assignable_v<_Er>
1350 {
1351 if (__x._M_has_value)
1352 emplace();
1353 else
1354 _M_assign_unex(__x._M_unex);
1355 return *this;
1356 }
1357
1358 constexpr expected&
1359 operator=(expected&& __x)
1360 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1361 is_nothrow_move_assignable<_Er>>)
1362 requires is_move_constructible_v<_Er>
1363 && is_move_assignable_v<_Er>
1364 {
1365 if (__x._M_has_value)
1366 emplace();
1367 else
1368 _M_assign_unex(std::move(__x._M_unex));
1369 return *this;
1370 }
1371
1372 template<typename _Gr>
1373 requires is_constructible_v<_Er, const _Gr&>
1374 && is_assignable_v<_Er&, const _Gr&>
1375 constexpr expected&
1376 operator=(const unexpected<_Gr>& __e)
1377 {
1378 _M_assign_unex(__e.error());
1379 return *this;
1380 }
1381
1382 template<typename _Gr>
1383 requires is_constructible_v<_Er, _Gr>
1384 && is_assignable_v<_Er&, _Gr>
1385 constexpr expected&
1386 operator=(unexpected<_Gr>&& __e)
1387 {
1388 _M_assign_unex(std::move(__e.error()));
1389 return *this;
1390 }
1391
1392 // modifiers
1393
1394 constexpr void
1395 emplace() noexcept
1396 {
1397 if (!_M_has_value)
1398 {
1399 std::destroy_at(__builtin_addressof(_M_unex));
1400 _M_has_value = true;
1401 }
1402 }
1403
1404 // swap
1405 constexpr void
1406 swap(expected& __x)
1407 noexcept(__and_v<is_nothrow_swappable<_Er&>,
1408 is_nothrow_move_constructible<_Er>>)
1409 requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1410 {
1411 if (_M_has_value)
1412 {
1413 if (!__x._M_has_value)
1414 {
1415 std::construct_at(__builtin_addressof(_M_unex),
1416 std::move(__x._M_unex)); // might throw
1417 std::destroy_at(__builtin_addressof(__x._M_unex));
1418 _M_has_value = false;
1419 __x._M_has_value = true;
1420 }
1421 }
1422 else
1423 {
1424 if (__x._M_has_value)
1425 {
1426 std::construct_at(__builtin_addressof(__x._M_unex),
1427 std::move(_M_unex)); // might throw
1428 std::destroy_at(__builtin_addressof(_M_unex));
1429 _M_has_value = true;
1430 __x._M_has_value = false;
1431 }
1432 else
1433 {
1434 using std::swap;
1435 swap(_M_unex, __x._M_unex);
1436 }
1437 }
1438 }
1439
1440 // observers
1441
1442 [[nodiscard]]
1443 constexpr explicit
1444 operator bool() const noexcept { return _M_has_value; }
1445
1446 [[nodiscard]]
1447 constexpr bool has_value() const noexcept { return _M_has_value; }
1448
1449 constexpr void
1450 operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1451
1452 constexpr void
1453 value() const&
1454 {
1455 if (_M_has_value) [[likely]]
1456 return;
1457 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1458 }
1459
1460 constexpr void
1461 value() &&
1462 {
1463 if (_M_has_value) [[likely]]
1464 return;
1465 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1466 }
1467
1468 constexpr const _Er&
1469 error() const & noexcept
1470 {
1471 __glibcxx_assert(!_M_has_value);
1472 return _M_unex;
1473 }
1474
1475 constexpr _Er&
1476 error() & noexcept
1477 {
1478 __glibcxx_assert(!_M_has_value);
1479 return _M_unex;
1480 }
1481
1482 constexpr const _Er&&
1483 error() const && noexcept
1484 {
1485 __glibcxx_assert(!_M_has_value);
1486 return std::move(_M_unex);
1487 }
1488
1489 constexpr _Er&&
1490 error() && noexcept
1491 {
1492 __glibcxx_assert(!_M_has_value);
1493 return std::move(_M_unex);
1494 }
1495
1496 template<typename _Gr = _Er>
1497 constexpr _Er
1498 error_or(_Gr&& __e) const&
1499 {
1500 static_assert( is_copy_constructible_v<_Er> );
1501 static_assert( is_convertible_v<_Gr, _Er> );
1502
1503 if (_M_has_value)
1504 return std::forward<_Gr>(__e);
1505 return _M_unex;
1506 }
1507
1508 template<typename _Gr = _Er>
1509 constexpr _Er
1510 error_or(_Gr&& __e) &&
1511 {
1512 static_assert( is_move_constructible_v<_Er> );
1513 static_assert( is_convertible_v<_Gr, _Er> );
1514
1515 if (_M_has_value)
1516 return std::forward<_Gr>(__e);
1517 return std::move(_M_unex);
1518 }
1519
1520 // monadic operations
1521
1522 template<typename _Fn> requires is_copy_constructible_v<_Er>
1523 constexpr auto
1524 and_then(_Fn&& __f) &
1525 {
1526 using _Up = __expected::__result0<_Fn>;
1527 static_assert(__expected::__is_expected<_Up>);
1528 static_assert(is_same_v<typename _Up::error_type, _Er>);
1529
1530 if (has_value())
1531 return std::__invoke(std::forward<_Fn>(__f));
1532 else
1533 return _Up(unexpect, error());
1534 }
1535
1536 template<typename _Fn> requires is_copy_constructible_v<_Er>
1537 constexpr auto
1538 and_then(_Fn&& __f) const &
1539 {
1540 using _Up = __expected::__result0<_Fn>;
1541 static_assert(__expected::__is_expected<_Up>);
1542 static_assert(is_same_v<typename _Up::error_type, _Er>);
1543
1544 if (has_value())
1545 return std::__invoke(std::forward<_Fn>(__f));
1546 else
1547 return _Up(unexpect, error());
1548 }
1549
1550 template<typename _Fn> requires is_move_constructible_v<_Er>
1551 constexpr auto
1552 and_then(_Fn&& __f) &&
1553 {
1554 using _Up = __expected::__result0<_Fn>;
1555 static_assert(__expected::__is_expected<_Up>);
1556 static_assert(is_same_v<typename _Up::error_type, _Er>);
1557
1558 if (has_value())
1559 return std::__invoke(std::forward<_Fn>(__f));
1560 else
1561 return _Up(unexpect, std::move(error()));
1562 }
1563
1564 template<typename _Fn> requires is_move_constructible_v<_Er>
1565 constexpr auto
1566 and_then(_Fn&& __f) const &&
1567 {
1568 using _Up = __expected::__result0<_Fn>;
1569 static_assert(__expected::__is_expected<_Up>);
1570 static_assert(is_same_v<typename _Up::error_type, _Er>);
1571
1572 if (has_value())
1573 return std::__invoke(std::forward<_Fn>(__f));
1574 else
1575 return _Up(unexpect, std::move(error()));
1576 }
1577
1578 template<typename _Fn>
1579 constexpr auto
1580 or_else(_Fn&& __f) &
1581 {
1582 using _Gr = __expected::__result<_Fn, _Er&>;
1583 static_assert(__expected::__is_expected<_Gr>);
1584 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1585
1586 if (has_value())
1587 return _Gr();
1588 else
1589 return std::__invoke(std::forward<_Fn>(__f), error());
1590 }
1591
1592 template<typename _Fn>
1593 constexpr auto
1594 or_else(_Fn&& __f) const &
1595 {
1596 using _Gr = __expected::__result<_Fn, const _Er&>;
1597 static_assert(__expected::__is_expected<_Gr>);
1598 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1599
1600 if (has_value())
1601 return _Gr();
1602 else
1603 return std::__invoke(std::forward<_Fn>(__f), error());
1604 }
1605
1606 template<typename _Fn>
1607 constexpr auto
1608 or_else(_Fn&& __f) &&
1609 {
1610 using _Gr = __expected::__result<_Fn, _Er&&>;
1611 static_assert(__expected::__is_expected<_Gr>);
1612 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1613
1614 if (has_value())
1615 return _Gr();
1616 else
1617 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
1618 }
1619
1620 template<typename _Fn>
1621 constexpr auto
1622 or_else(_Fn&& __f) const &&
1623 {
1624 using _Gr = __expected::__result<_Fn, const _Er&&>;
1625 static_assert(__expected::__is_expected<_Gr>);
1626 static_assert(is_same_v<typename _Gr::value_type, _Tp>);
1627
1628 if (has_value())
1629 return _Gr();
1630 else
1631 return std::__invoke(std::forward<_Fn>(__f), std::move(error()));
1632 }
1633
1634 template<typename _Fn> requires is_copy_constructible_v<_Er>
1635 constexpr auto
1636 transform(_Fn&& __f) &
1637 {
1638 using _Up = __expected::__result0_xform<_Fn>;
1639 using _Res = expected<_Up, _Er>;
1640
1641 if (has_value())
1642 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1643 else
1644 return _Res(unexpect, error());
1645 }
1646
1647 template<typename _Fn> requires is_copy_constructible_v<_Er>
1648 constexpr auto
1649 transform(_Fn&& __f) const &
1650 {
1651 using _Up = __expected::__result0_xform<_Fn>;
1652 using _Res = expected<_Up, _Er>;
1653
1654 if (has_value())
1655 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1656 else
1657 return _Res(unexpect, error());
1658 }
1659
1660 template<typename _Fn> requires is_move_constructible_v<_Er>
1661 constexpr auto
1662 transform(_Fn&& __f) &&
1663 {
1664 using _Up = __expected::__result0_xform<_Fn>;
1665 using _Res = expected<_Up, _Er>;
1666
1667 if (has_value())
1668 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1669 else
1670 return _Res(unexpect, std::move(error()));
1671 }
1672
1673 template<typename _Fn> requires is_move_constructible_v<_Er>
1674 constexpr auto
1675 transform(_Fn&& __f) const &&
1676 {
1677 using _Up = __expected::__result0_xform<_Fn>;
1678 using _Res = expected<_Up, _Er>;
1679
1680 if (has_value())
1681 return _Res(__in_place_inv{}, std::forward<_Fn>(__f));
1682 else
1683 return _Res(unexpect, std::move(error()));
1684 }
1685
1686 template<typename _Fn>
1687 constexpr auto
1688 transform_error(_Fn&& __f) &
1689 {
1690 using _Gr = __expected::__result_xform<_Fn, _Er&>;
1691 using _Res = expected<_Tp, _Gr>;
1692
1693 if (has_value())
1694 return _Res();
1695 else
1696 return _Res(__unexpect_inv{}, [&]() {
1697 return std::__invoke(std::forward<_Fn>(__f),
1698 _M_unex);
1699 });
1700 }
1701
1702 template<typename _Fn>
1703 constexpr auto
1704 transform_error(_Fn&& __f) const &
1705 {
1706 using _Gr = __expected::__result_xform<_Fn, const _Er&>;
1707 using _Res = expected<_Tp, _Gr>;
1708
1709 if (has_value())
1710 return _Res();
1711 else
1712 return _Res(__unexpect_inv{}, [&]() {
1713 return std::__invoke(std::forward<_Fn>(__f),
1714 _M_unex);
1715 });
1716 }
1717
1718 template<typename _Fn>
1719 constexpr auto
1720 transform_error(_Fn&& __f) &&
1721 {
1722 using _Gr = __expected::__result_xform<_Fn, _Er&&>;
1723 using _Res = expected<_Tp, _Gr>;
1724
1725 if (has_value())
1726 return _Res();
1727 else
1728 return _Res(__unexpect_inv{}, [&]() {
1729 return std::__invoke(std::forward<_Fn>(__f),
1730 std::move(_M_unex));
1731 });
1732 }
1733
1734 template<typename _Fn>
1735 constexpr auto
1736 transform_error(_Fn&& __f) const &&
1737 {
1738 using _Gr = __expected::__result_xform<_Fn, const _Er&&>;
1739 using _Res = expected<_Tp, _Gr>;
1740
1741 if (has_value())
1742 return _Res();
1743 else
1744 return _Res(__unexpect_inv{}, [&]() {
1745 return std::__invoke(std::forward<_Fn>(__f),
1746 std::move(_M_unex));
1747 });
1748 }
1749
1750 // equality operators
1751
1752 template<typename _Up, typename _Er2>
1753 requires is_void_v<_Up>
1754 friend constexpr bool
1755 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1756 // FIXME: noexcept(noexcept(bool(__x.error() == __y.error())))
1757 {
1758 if (__x.has_value())
1759 return __y.has_value();
1760 else
1761 return !__y.has_value() && bool(__x.error() == __y.error());
1762 }
1763
1764 template<typename _Er2>
1765 friend constexpr bool
1766 operator==(const expected& __x, const unexpected<_Er2>& __e)
1767 // FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
1768 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1769
1770 friend constexpr void
1771 swap(expected& __x, expected& __y)
1772 noexcept(noexcept(__x.swap(__y)))
1773 requires requires { __x.swap(__y); }
1774 { __x.swap(__y); }
1775
1776 private:
1777 template<typename, typename> friend class expected;
1778
1779 template<typename _Vp>
1780 constexpr void
1781 _M_assign_unex(_Vp&& __v)
1782 {
1783 if (_M_has_value)
1784 {
1785 std::construct_at(__builtin_addressof(_M_unex),
1786 std::forward<_Vp>(__v));
1787 _M_has_value = false;
1788 }
1789 else
1790 _M_unex = std::forward<_Vp>(__v);
1791 }
1792
1793 using __in_place_inv = __expected::__in_place_inv;
1794 using __unexpect_inv = __expected::__unexpect_inv;
1795
1796 template<typename _Fn>
1797 explicit constexpr
1798 expected(__in_place_inv, _Fn&& __fn)
1799 : _M_void(), _M_has_value(true)
1800 { std::forward<_Fn>(__fn)(); }
1801
1802 template<typename _Fn>
1803 explicit constexpr
1804 expected(__unexpect_inv, _Fn&& __fn)
1805 : _M_unex(std::forward<_Fn>(__fn)()), _M_has_value(false)
1806 { }
1807
1808 union {
1809 struct { } _M_void;
1810 _Er _M_unex;
1811 };
1812
1813 bool _M_has_value;
1814 };
1815 /// @}
1816
1817_GLIBCXX_END_NAMESPACE_VERSION
1818} // namespace std
1819
1820#endif // C++23
1821#endif // _GLIBCXX_EXPECTED