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/stl_construct.h> // construct_at
39#include <bits/utility.h> // in_place_t
40
41namespace std _GLIBCXX_VISIBILITY(default)
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45 /**
46 * @defgroup expected_values Expected values
47 * @addtogroup utilities
48 * @since C++23
49 * @{
50 */
51
52#define __cpp_lib_expected 202202L
53
54 /// Discriminated union that holds an expected value or an error value.
55 /**
56 * @since C++23
57 */
58 template<typename _Tp, typename _Er>
59 class expected;
60
61 /// Wrapper type used to pass an error value to a `std::expected`.
62 /**
63 * @since C++23
64 */
65 template<typename _Er>
66 class unexpected;
67
68 /// Exception thrown by std::expected when the value() is not present.
69 /**
70 * @since C++23
71 */
72 template<typename _Er>
73 class bad_expected_access;
74
75 template<>
76 class bad_expected_access<void> : public exception
77 {
78 protected:
79 bad_expected_access() noexcept { }
80 bad_expected_access(const bad_expected_access&) = default;
81 bad_expected_access(bad_expected_access&&) = default;
82 bad_expected_access& operator=(const bad_expected_access&) = default;
83 bad_expected_access& operator=(bad_expected_access&&) = default;
84 ~bad_expected_access() = default;
85
86 public:
87
88 [[nodiscard]]
89 const char*
90 what() const noexcept override
91 { return "bad access to std::expected without expected value"; }
92 };
93
94 template<typename _Er>
95 class bad_expected_access : public bad_expected_access<void> {
96 public:
97 explicit
98 bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
99
100 // XXX const char* what() const noexcept override;
101
102 [[nodiscard]]
103 _Er&
104 error() & noexcept
105 { return _M_unex; }
106
107 [[nodiscard]]
108 const _Er&
109 error() const & noexcept
110 { return _M_unex; }
111
112 [[nodiscard]]
113 _Er&&
114 error() && noexcept
115 { return std::move(_M_unex); }
116
117 [[nodiscard]]
118 const _Er&&
119 error() const && noexcept
120 { return std::move(_M_unex); }
121
122 private:
123 _Er _M_unex;
124 };
125
126 /// Tag type for constructing unexpected values in a std::expected
127 /**
128 * @since C++23
129 */
130 struct unexpect_t
131 {
132 explicit unexpect_t() = default;
133 };
134
135 /// Tag for constructing unexpected values in a std::expected
136 /**
137 * @since C++23
138 */
139 inline constexpr unexpect_t unexpect{};
140
141/// @cond undoc
142namespace __expected
143{
144 template<typename _Tp>
145 constexpr bool __is_expected = false;
146 template<typename _Tp, typename _Er>
147 constexpr bool __is_expected<expected<_Tp, _Er>> = true;
148
149 template<typename _Tp>
150 constexpr bool __is_unexpected = false;
151 template<typename _Tp>
152 constexpr bool __is_unexpected<unexpected<_Tp>> = true;
153
154 template<typename _Er>
155 concept __can_be_unexpected
156 = is_object_v<_Er> && (!is_array_v<_Er>)
157 && (!__expected::__is_unexpected<_Er>)
158 && (!is_const_v<_Er>) && (!is_volatile_v<_Er>);
159}
160/// @endcond
161
162 template<typename _Er>
163 class unexpected
164 {
165 static_assert( __expected::__can_be_unexpected<_Er> );
166
167 public:
168 constexpr unexpected(const unexpected&) = default;
169 constexpr unexpected(unexpected&&) = default;
170
171 template<typename _Err = _Er>
172 requires (!is_same_v<remove_cvref_t<_Err>, unexpected>)
173 && (!is_same_v<remove_cvref_t<_Err>, in_place_t>)
174 && is_constructible_v<_Er, _Err>
175 constexpr explicit
176 unexpected(_Err&& __e)
177 noexcept(is_nothrow_constructible_v<_Er, _Err>)
178 : _M_unex(std::forward<_Err>(__e))
179 { }
180
181 template<typename... _Args>
182 requires is_constructible_v<_Er, _Args...>
183 constexpr explicit
184 unexpected(in_place_t, _Args&&... __args)
185 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
186 : _M_unex(std::forward<_Args>(__args)...)
187 { }
188
189 template<typename _Up, typename... _Args>
190 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
191 constexpr explicit
192 unexpected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
193 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
194 _Args...>)
195 : _M_unex(__il, std::forward<_Args>(__args)...)
196 { }
197
198 constexpr unexpected& operator=(const unexpected&) = default;
199 constexpr unexpected& operator=(unexpected&&) = default;
200
201
202 [[nodiscard]]
203 constexpr const _Er&
204 error() const & noexcept { return _M_unex; }
205
206 [[nodiscard]]
207 constexpr _Er&
208 error() & noexcept { return _M_unex; }
209
210 [[nodiscard]]
211 constexpr const _Er&&
212 error() const && noexcept { return std::move(_M_unex); }
213
214 [[nodiscard]]
215 constexpr _Er&&
216 error() && noexcept { return std::move(_M_unex); }
217
218 constexpr void
219 swap(unexpected& __other) noexcept(is_nothrow_swappable_v<_Er>)
220 {
221 static_assert( is_swappable_v<_Er> );
222 using std::swap;
223 swap(_M_unex, __other._M_unex);
224 }
225
226 template<typename _Err>
227 [[nodiscard]]
228 friend constexpr bool
229 operator==(const unexpected& __x, const unexpected<_Err>& __y)
230 { return __x._M_unex == __y.error(); }
231
232 friend constexpr void
233 swap(unexpected& __x, unexpected& __y)
234 noexcept(noexcept(__x.swap(__y)))
235 requires requires {__x.swap(__y);}
236 { __x.swap(__y); }
237
238 private:
239 _Er _M_unex;
240 };
241
242 template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
243
244/// @cond undoc
245namespace __expected
246{
247 template<typename _Tp>
248 struct _Guard
249 {
250 static_assert( is_nothrow_move_constructible_v<_Tp> );
251
252 constexpr explicit
253 _Guard(_Tp& __x)
254 : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
255 { std::destroy_at(_M_guarded); }
256
257 constexpr
258 ~_Guard()
259 {
260 if (_M_guarded) [[unlikely]]
261 std::construct_at(_M_guarded, std::move(_M_tmp));
262 }
263
264 _Guard(const _Guard&) = delete;
265 _Guard& operator=(const _Guard&) = delete;
266
267 constexpr _Tp&&
268 release() noexcept
269 {
270 _M_guarded = nullptr;
271 return std::move(_M_tmp);
272 }
273
274 private:
275 _Tp* _M_guarded;
276 _Tp _M_tmp;
277 };
278
279 // reinit-expected helper from [expected.object.assign]
280 template<typename _Tp, typename _Up, typename _Vp>
281 constexpr void
282 __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
283 noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
284 {
285 if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
286 {
287 std::destroy_at(__oldval);
288 std::construct_at(__newval, std::forward<_Vp>(__arg));
289 }
290 else if constexpr (is_nothrow_move_constructible_v<_Tp>)
291 {
292 _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
293 std::destroy_at(__oldval);
294 std::construct_at(__newval, std::move(__tmp));
295 }
296 else
297 {
298 _Guard<_Up> __guard(*__oldval);
299 std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
300 __guard.release();
301 }
302 }
303}
304/// @endcond
305
306 template<typename _Tp, typename _Er>
307 class expected
308 {
309 static_assert( ! is_reference_v<_Tp> );
310 static_assert( ! is_function_v<_Tp> );
311 static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
312 static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
313 static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
314 static_assert( __expected::__can_be_unexpected<_Er> );
315
316 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
317 static constexpr bool __cons_from_expected
318 = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
319 is_constructible<_Tp, expected<_Up, _Err>>,
320 is_constructible<_Tp, const expected<_Up, _Err>&>,
321 is_constructible<_Tp, const expected<_Up, _Err>>,
322 is_convertible<expected<_Up, _Err>&, _Tp>,
323 is_convertible<expected<_Up, _Err>, _Tp>,
324 is_convertible<const expected<_Up, _Err>&, _Tp>,
325 is_convertible<const expected<_Up, _Err>, _Tp>,
326 is_constructible<_Unex, expected<_Up, _Err>&>,
327 is_constructible<_Unex, expected<_Up, _Err>>,
328 is_constructible<_Unex, const expected<_Up, _Err>&>,
329 is_constructible<_Unex, const expected<_Up, _Err>>
330 >;
331
332 template<typename _Up, typename _Err>
333 constexpr static bool __explicit_conv
334 = __or_v<__not_<is_convertible<_Up, _Tp>>,
335 __not_<is_convertible<_Err, _Er>>
336 >;
337
338 public:
339 using value_type = _Tp;
340 using error_type = _Er;
341 using unexpected_type = unexpected<_Er>;
342
343 template<typename _Up>
344 using rebind = expected<_Up, error_type>;
345
346 constexpr
347 expected()
348 noexcept(is_nothrow_default_constructible_v<_Tp>)
349 requires is_default_constructible_v<_Tp>
350 : _M_val(), _M_has_value(true)
351 { }
352
353 expected(const expected&) = default;
354
355 constexpr
356 expected(const expected& __x)
357 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
358 is_nothrow_copy_constructible<_Er>>)
359 requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
360 && (!is_trivially_copy_constructible_v<_Tp>
361 || !is_trivially_copy_constructible_v<_Er>)
362 : _M_invalid(), _M_has_value(__x._M_has_value)
363 {
364 if (_M_has_value)
365 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
366 else
367 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
368 }
369
370 expected(expected&&) = default;
371
372 constexpr
373 expected(expected&& __x)
374 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
375 is_nothrow_move_constructible<_Er>>)
376 requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
377 && (!is_trivially_move_constructible_v<_Tp>
378 || !is_trivially_move_constructible_v<_Er>)
379 : _M_invalid(), _M_has_value(__x._M_has_value)
380 {
381 if (_M_has_value)
382 std::construct_at(__builtin_addressof(_M_val),
383 std::move(__x)._M_val);
384 else
385 std::construct_at(__builtin_addressof(_M_unex),
386 std::move(__x)._M_unex);
387 }
388
389 template<typename _Up, typename _Gr>
390 requires is_constructible_v<_Tp, const _Up&>
391 && is_constructible_v<_Er, const _Gr&>
392 && (!__cons_from_expected<_Up, _Gr>)
393 constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
394 expected(const expected<_Up, _Gr>& __x)
395 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
396 is_nothrow_constructible<_Er, const _Gr&>>)
397 : _M_invalid(), _M_has_value(__x._M_has_value)
398 {
399 if (_M_has_value)
400 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
401 else
402 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
403 }
404
405 template<typename _Up, typename _Gr>
406 requires is_constructible_v<_Tp, _Up>
407 && is_constructible_v<_Er, _Gr>
408 && (!__cons_from_expected<_Up, _Gr>)
409 constexpr explicit(__explicit_conv<_Up, _Gr>)
410 expected(expected<_Up, _Gr>&& __x)
411 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
412 is_nothrow_constructible<_Er, _Gr>>)
413 : _M_invalid(), _M_has_value(__x._M_has_value)
414 {
415 if (_M_has_value)
416 std::construct_at(__builtin_addressof(_M_val),
417 std::move(__x)._M_val);
418 else
419 std::construct_at(__builtin_addressof(_M_unex),
420 std::move(__x)._M_unex);
421 }
422
423 template<typename _Up = _Tp>
424 requires (!is_same_v<remove_cvref_t<_Up>, expected>)
425 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
426 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
427 && is_constructible_v<_Tp, _Up>
428 constexpr explicit(!is_convertible_v<_Up, _Tp>)
429 expected(_Up&& __v)
430 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
431 : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
432 { }
433
434 template<typename _Gr = _Er>
435 requires is_constructible_v<_Er, const _Gr&>
436 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
437 expected(const unexpected<_Gr>& __u)
438 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
439 : _M_unex(__u.error()), _M_has_value(false)
440 { }
441
442 template<typename _Gr = _Er>
443 requires is_constructible_v<_Er, _Gr>
444 constexpr explicit(!is_convertible_v<_Gr, _Er>)
445 expected(unexpected<_Gr>&& __u)
446 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
447 : _M_unex(std::move(__u).error()), _M_has_value(false)
448 { }
449
450 template<typename... _Args>
451 requires is_constructible_v<_Tp, _Args...>
452 constexpr explicit
453 expected(in_place_t, _Args&&... __args)
454 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
455 : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
456 { }
457
458 template<typename _Up, typename... _Args>
459 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
460 constexpr explicit
461 expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
462 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
463 _Args...>)
464 : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
465 { }
466
467 template<typename... _Args>
468 requires is_constructible_v<_Er, _Args...>
469 constexpr explicit
470 expected(unexpect_t, _Args&&... __args)
471 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
472 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
473 { }
474
475 template<typename _Up, typename... _Args>
476 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
477 constexpr explicit
478 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
479 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
480 _Args...>)
481 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
482 { }
483
484 constexpr ~expected() = default;
485
486 constexpr ~expected()
487 requires (!is_trivially_destructible_v<_Tp>)
488 || (!is_trivially_destructible_v<_Er>)
489 {
490 if (_M_has_value)
491 std::destroy_at(__builtin_addressof(_M_val));
492 else
493 std::destroy_at(__builtin_addressof(_M_unex));
494 }
495
496 // assignment
497
498 expected& operator=(const expected&) = delete;
499
500 constexpr expected&
501 operator=(const expected& __x)
502 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
503 is_nothrow_copy_constructible<_Er>,
504 is_nothrow_copy_assignable<_Tp>,
505 is_nothrow_copy_assignable<_Er>>)
506 requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
507 && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
508 && (is_nothrow_move_constructible_v<_Tp>
509 || is_nothrow_move_constructible_v<_Er>)
510 {
511 if (__x._M_has_value)
512 this->_M_assign_val(__x._M_val);
513 else
514 this->_M_assign_unex(__x._M_unex);
515 return *this;
516 }
517
518 constexpr expected&
519 operator=(expected&& __x)
520 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
521 is_nothrow_move_constructible<_Er>,
522 is_nothrow_move_assignable<_Tp>,
523 is_nothrow_move_assignable<_Er>>)
524 requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
525 && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
526 && (is_nothrow_move_constructible_v<_Tp>
527 || is_nothrow_move_constructible_v<_Er>)
528 {
529 if (__x._M_has_value)
530 _M_assign_val(std::move(__x._M_val));
531 else
532 _M_assign_unex(std::move(__x._M_unex));
533 return *this;
534 }
535
536 template<typename _Up = _Tp>
537 requires (!is_same_v<expected, remove_cvref_t<_Up>>)
538 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
539 && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
540 && (is_nothrow_constructible_v<_Tp, _Up>
541 || is_nothrow_move_constructible_v<_Tp>
542 || is_nothrow_move_constructible_v<_Er>)
543 constexpr expected&
544 operator=(_Up&& __v)
545 {
546 _M_assign_val(std::forward<_Up>(__v));
547 return *this;
548 }
549
550 template<typename _Gr>
551 requires is_constructible_v<_Er, const _Gr&>
552 && is_assignable_v<_Er&, const _Gr&>
553 && (is_nothrow_constructible_v<_Er, const _Gr&>
554 || is_nothrow_move_constructible_v<_Tp>
555 || is_nothrow_move_constructible_v<_Er>)
556 constexpr expected&
557 operator=(const unexpected<_Gr>& __e)
558 {
559 _M_assign_unex(__e.error());
560 return *this;
561 }
562
563 template<typename _Gr>
564 requires is_constructible_v<_Er, _Gr>
565 && is_assignable_v<_Er&, _Gr>
566 && (is_nothrow_constructible_v<_Er, _Gr>
567 || is_nothrow_move_constructible_v<_Tp>
568 || is_nothrow_move_constructible_v<_Er>)
569 constexpr expected&
570 operator=(unexpected<_Gr>&& __e)
571 {
572 _M_assign_unex(std::move(__e).error());
573 return *this;
574 }
575
576 // modifiers
577
578 template<typename... _Args>
579 requires is_nothrow_constructible_v<_Tp, _Args...>
580 constexpr _Tp&
581 emplace(_Args&&... __args) noexcept
582 {
583 if (_M_has_value)
584 std::destroy_at(__builtin_addressof(_M_val));
585 else
586 {
587 std::destroy_at(__builtin_addressof(_M_unex));
588 _M_has_value = true;
589 }
590 std::construct_at(__builtin_addressof(_M_val),
591 std::forward<_Args>(__args)...);
592 return _M_val;
593 }
594
595 template<typename _Up, typename... _Args>
596 requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
597 _Args...>
598 constexpr _Tp&
599 emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
600 {
601 if (_M_has_value)
602 std::destroy_at(__builtin_addressof(_M_val));
603 else
604 {
605 std::destroy_at(__builtin_addressof(_M_unex));
606 _M_has_value = true;
607 }
608 std::construct_at(__builtin_addressof(_M_val),
609 __il, std::forward<_Args>(__args)...);
610 return _M_val;
611 }
612
613 // swap
614 constexpr void
615 swap(expected& __x)
616 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
617 is_nothrow_move_constructible<_Er>,
618 is_nothrow_swappable<_Tp&>,
619 is_nothrow_swappable<_Er&>>)
620 requires is_swappable_v<_Tp> && is_swappable_v<_Er>
621 && is_move_constructible_v<_Tp>
622 && is_move_constructible_v<_Er>
623 && (is_nothrow_move_constructible_v<_Tp>
624 || is_nothrow_move_constructible_v<_Er>)
625 {
626 if (_M_has_value)
627 {
628 if (__x._M_has_value)
629 {
630 using std::swap;
631 swap(_M_val, __x._M_val);
632 }
633 else
634 this->_M_swap_val_unex(__x);
635 }
636 else
637 {
638 if (__x._M_has_value)
639 __x._M_swap_val_unex(*this);
640 else
641 {
642 using std::swap;
643 swap(_M_unex, __x._M_unex);
644 }
645 }
646 }
647
648 // observers
649
650 [[nodiscard]]
651 constexpr const _Tp*
652 operator->() const noexcept
653 {
654 __glibcxx_assert(_M_has_value);
655 return __builtin_addressof(_M_val);
656 }
657
658 [[nodiscard]]
659 constexpr _Tp*
660 operator->() noexcept
661 {
662 __glibcxx_assert(_M_has_value);
663 return __builtin_addressof(_M_val);
664 }
665
666 [[nodiscard]]
667 constexpr const _Tp&
668 operator*() const & noexcept
669 {
670 __glibcxx_assert(_M_has_value);
671 return _M_val;
672 }
673
674 [[nodiscard]]
675 constexpr _Tp&
676 operator*() & noexcept
677 {
678 __glibcxx_assert(_M_has_value);
679 return _M_val;
680 }
681
682 [[nodiscard]]
683 constexpr const _Tp&&
684 operator*() const && noexcept
685 {
686 __glibcxx_assert(_M_has_value);
687 return std::move(_M_val);
688 }
689
690 [[nodiscard]]
691 constexpr _Tp&&
692 operator*() && noexcept
693 {
694 __glibcxx_assert(_M_has_value);
695 return std::move(_M_val);
696 }
697
698 [[nodiscard]]
699 constexpr explicit
700 operator bool() const noexcept { return _M_has_value; }
701
702 [[nodiscard]]
703 constexpr bool has_value() const noexcept { return _M_has_value; }
704
705 constexpr const _Tp&
706 value() const &
707 {
708 if (_M_has_value) [[likely]]
709 return _M_val;
710 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
711 }
712
713 constexpr _Tp&
714 value() &
715 {
716 if (_M_has_value) [[likely]]
717 return _M_val;
718 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
719 }
720
721 constexpr const _Tp&&
722 value() const &&
723 {
724 if (_M_has_value) [[likely]]
725 return std::move(_M_val);
726 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
727 std::move(_M_unex)));
728 }
729
730 constexpr _Tp&&
731 value() &&
732 {
733 if (_M_has_value) [[likely]]
734 return std::move(_M_val);
735 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(
736 std::move(_M_unex)));
737 }
738
739 constexpr const _Er&
740 error() const & noexcept
741 {
742 __glibcxx_assert(!_M_has_value);
743 return _M_unex;
744 }
745
746 constexpr _Er&
747 error() & noexcept
748 {
749 __glibcxx_assert(!_M_has_value);
750 return _M_unex;
751 }
752
753 constexpr const _Er&&
754 error() const && noexcept
755 {
756 __glibcxx_assert(!_M_has_value);
757 return std::move(_M_unex);
758 }
759
760 constexpr _Er&&
761 error() && noexcept
762 {
763 __glibcxx_assert(!_M_has_value);
764 return std::move(_M_unex);
765 }
766
767 template<typename _Up>
768 constexpr _Tp
769 value_or(_Up&& __v) const &
770 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
771 is_nothrow_convertible<_Up, _Tp>>)
772 {
773 static_assert( is_copy_constructible_v<_Tp> );
774 static_assert( is_convertible_v<_Up, _Tp> );
775
776 if (_M_has_value)
777 return _M_val;
778 return static_cast<_Tp>(std::forward<_Up>(__v));
779 }
780
781 template<typename _Up>
782 constexpr _Tp
783 value_or(_Up&& __v) &&
784 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
785 is_nothrow_convertible<_Up, _Tp>>)
786 {
787 static_assert( is_move_constructible_v<_Tp> );
788 static_assert( is_convertible_v<_Up, _Tp> );
789
790 if (_M_has_value)
791 return std::move(_M_val);
792 return static_cast<_Tp>(std::forward<_Up>(__v));
793 }
794
795 // equality operators
796
797 template<typename _Up, typename _Er2>
798 requires (!is_void_v<_Up>)
799 friend constexpr bool
800 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
801 noexcept(noexcept(bool(*__x == *__y))
802 && noexcept(bool(__x.error() == __y.error())))
803 {
804 if (__x.has_value())
805 return __y.has_value() && bool(*__x == *__y);
806 else
807 return !__y.has_value() && bool(__x.error() == __y.error());
808 }
809
810 template<typename _Up>
811 friend constexpr bool
812 operator==(const expected& __x, const _Up& __v)
813 noexcept(noexcept(bool(*__x == __v)))
814 { return __x.has_value() && bool(*__x == __v); }
815
816 template<typename _Er2>
817 friend constexpr bool
818 operator==(const expected& __x, const unexpected<_Er2>& __e)
819 noexcept(noexcept(bool(__x.error() == __e.error())))
820 { return !__x.has_value() && bool(__x.error() == __e.error()); }
821
822 friend constexpr void
823 swap(expected& __x, expected& __y)
824 noexcept(noexcept(__x.swap(__y)))
825 requires requires {__x.swap(__y);}
826 { __x.swap(__y); }
827
828 private:
829 template<typename, typename> friend class expected;
830
831 template<typename _Vp>
832 constexpr void
833 _M_assign_val(_Vp&& __v)
834 {
835 if (_M_has_value)
836 _M_val = std::forward<_Vp>(__v);
837 else
838 {
839 __expected::__reinit(__builtin_addressof(_M_val),
840 __builtin_addressof(_M_unex),
841 std::forward<_Vp>(__v));
842 _M_has_value = true;
843 }
844 }
845
846 template<typename _Vp>
847 constexpr void
848 _M_assign_unex(_Vp&& __v)
849 {
850 if (_M_has_value)
851 {
852 __expected::__reinit(__builtin_addressof(_M_unex),
853 __builtin_addressof(_M_val),
854 std::forward<_Vp>(__v));
855 _M_has_value = false;
856 }
857 else
858 _M_unex = std::forward<_Vp>(__v);
859 }
860
861 // Swap two expected objects when only one has a value.
862 // Precondition: this->_M_has_value && !__rhs._M_has_value
863 constexpr void
864 _M_swap_val_unex(expected& __rhs)
865 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
866 is_nothrow_move_constructible<_Tp>>)
867 {
868 if constexpr (is_nothrow_move_constructible_v<_Er>)
869 {
870 __expected::_Guard<_Er> __guard(__rhs._M_unex);
871 std::construct_at(__builtin_addressof(__rhs._M_val),
872 std::move(_M_val)); // might throw
873 __rhs._M_has_value = true;
874 std::destroy_at(__builtin_addressof(_M_val));
875 std::construct_at(__builtin_addressof(_M_unex),
876 __guard.release());
877 _M_has_value = false;
878 }
879 else
880 {
881 __expected::_Guard<_Tp> __guard(__rhs._M_val);
882 std::construct_at(__builtin_addressof(_M_unex),
883 std::move(__rhs._M_unex)); // might throw
884 _M_has_value = false;
885 std::destroy_at(__builtin_addressof(__rhs._M_unex));
886 std::construct_at(__builtin_addressof(__rhs._M_val),
887 __guard.release());
888 __rhs._M_has_value = true;
889 }
890 }
891
892 union {
893 struct { } _M_invalid;
894 _Tp _M_val;
895 _Er _M_unex;
896 };
897
898 bool _M_has_value;
899 };
900
901 // Partial specialization for std::expected<cv void, E>
902 template<typename _Tp, typename _Er> requires is_void_v<_Tp>
903 class expected<_Tp, _Er>
904 {
905 static_assert( __expected::__can_be_unexpected<_Er> );
906
907 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
908 static constexpr bool __cons_from_expected
909 = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
910 is_constructible<_Unex, expected<_Up, _Err>>,
911 is_constructible<_Unex, const expected<_Up, _Err>&>,
912 is_constructible<_Unex, const expected<_Up, _Err>>
913 >;
914
915 public:
916 using value_type = _Tp;
917 using error_type = _Er;
918 using unexpected_type = unexpected<_Er>;
919
920 template<typename _Up>
921 using rebind = expected<_Up, error_type>;
922
923 constexpr
924 expected() noexcept
925 : _M_void(), _M_has_value(true)
926 { }
927
928 expected(const expected&) = default;
929
930 constexpr
931 expected(const expected& __x)
932 noexcept(is_nothrow_copy_constructible_v<_Er>)
933 requires is_copy_constructible_v<_Er>
934 && (!is_trivially_copy_constructible_v<_Er>)
935 : _M_void(), _M_has_value(__x._M_has_value)
936 {
937 if (!_M_has_value)
938 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
939 }
940
941 expected(expected&&) = default;
942
943 constexpr
944 expected(expected&& __x)
945 noexcept(is_nothrow_move_constructible_v<_Er>)
946 requires is_move_constructible_v<_Er>
947 && (!is_trivially_move_constructible_v<_Er>)
948 : _M_void(), _M_has_value(__x._M_has_value)
949 {
950 if (!_M_has_value)
951 std::construct_at(__builtin_addressof(_M_unex),
952 std::move(__x)._M_unex);
953 }
954
955 template<typename _Up, typename _Gr>
956 requires is_void_v<_Up>
957 && is_constructible_v<_Er, const _Gr&>
958 && (!__cons_from_expected<_Up, _Gr>)
959 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
960 expected(const expected<_Up, _Gr>& __x)
961 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
962 : _M_void(), _M_has_value(__x._M_has_value)
963 {
964 if (!_M_has_value)
965 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
966 }
967
968 template<typename _Up, typename _Gr>
969 requires is_void_v<_Up>
970 && is_constructible_v<_Er, _Gr>
971 && (!__cons_from_expected<_Up, _Gr>)
972 constexpr explicit(!is_convertible_v<_Gr, _Er>)
973 expected(expected<_Up, _Gr>&& __x)
974 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
975 : _M_void(), _M_has_value(__x._M_has_value)
976 {
977 if (!_M_has_value)
978 std::construct_at(__builtin_addressof(_M_unex),
979 std::move(__x)._M_unex);
980 }
981
982 template<typename _Gr = _Er>
983 requires is_constructible_v<_Er, const _Gr&>
984 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
985 expected(const unexpected<_Gr>& __u)
986 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
987 : _M_unex(__u.error()), _M_has_value(false)
988 { }
989
990 template<typename _Gr = _Er>
991 requires is_constructible_v<_Er, _Gr>
992 constexpr explicit(!is_convertible_v<_Gr, _Er>)
993 expected(unexpected<_Gr>&& __u)
994 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
995 : _M_unex(std::move(__u).error()), _M_has_value(false)
996 { }
997
998 template<typename... _Args>
999 constexpr explicit
1000 expected(in_place_t) noexcept
1001 : expected()
1002 { }
1003
1004 template<typename... _Args>
1005 requires is_constructible_v<_Er, _Args...>
1006 constexpr explicit
1007 expected(unexpect_t, _Args&&... __args)
1008 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1009 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1010 { }
1011
1012 template<typename _Up, typename... _Args>
1013 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1014 constexpr explicit
1015 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1016 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1017 _Args...>)
1018 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1019 { }
1020
1021 constexpr ~expected() = default;
1022
1023 constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1024 {
1025 if (!_M_has_value)
1026 std::destroy_at(__builtin_addressof(_M_unex));
1027 }
1028
1029 // assignment
1030
1031 expected& operator=(const expected&) = delete;
1032
1033 constexpr expected&
1034 operator=(const expected& __x)
1035 noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1036 is_nothrow_copy_assignable<_Er>>)
1037 requires is_copy_constructible_v<_Er>
1038 && is_copy_assignable_v<_Er>
1039 {
1040 if (__x._M_has_value)
1041 emplace();
1042 else
1043 _M_assign_unex(__x._M_unex);
1044 return *this;
1045 }
1046
1047 constexpr expected&
1048 operator=(expected&& __x)
1049 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1050 is_nothrow_move_assignable<_Er>>)
1051 requires is_move_constructible_v<_Er>
1052 && is_move_assignable_v<_Er>
1053 {
1054 if (__x._M_has_value)
1055 emplace();
1056 else
1057 _M_assign_unex(std::move(__x._M_unex));
1058 return *this;
1059 }
1060
1061 template<typename _Gr>
1062 requires is_constructible_v<_Er, const _Gr&>
1063 && is_assignable_v<_Er&, const _Gr&>
1064 constexpr expected&
1065 operator=(const unexpected<_Gr>& __e)
1066 {
1067 _M_assign_unex(__e.error());
1068 return *this;
1069 }
1070
1071 template<typename _Gr>
1072 requires is_constructible_v<_Er, _Gr>
1073 && is_assignable_v<_Er&, _Gr>
1074 constexpr expected&
1075 operator=(unexpected<_Gr>&& __e)
1076 {
1077 _M_assign_unex(std::move(__e.error()));
1078 return *this;
1079 }
1080
1081 // modifiers
1082
1083 constexpr void
1084 emplace() noexcept
1085 {
1086 if (!_M_has_value)
1087 {
1088 std::destroy_at(__builtin_addressof(_M_unex));
1089 _M_has_value = true;
1090 }
1091 }
1092
1093 // swap
1094 constexpr void
1095 swap(expected& __x)
1096 noexcept(__and_v<is_nothrow_swappable<_Er&>,
1097 is_nothrow_move_constructible<_Er>>)
1098 requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1099 {
1100 if (_M_has_value)
1101 {
1102 if (!__x._M_has_value)
1103 {
1104 std::construct_at(__builtin_addressof(_M_unex),
1105 std::move(__x._M_unex)); // might throw
1106 std::destroy_at(__builtin_addressof(__x._M_unex));
1107 _M_has_value = false;
1108 __x._M_has_value = true;
1109 }
1110 }
1111 else
1112 {
1113 if (__x._M_has_value)
1114 {
1115 std::construct_at(__builtin_addressof(__x._M_unex),
1116 std::move(_M_unex)); // might throw
1117 std::destroy_at(__builtin_addressof(_M_unex));
1118 _M_has_value = true;
1119 __x._M_has_value = false;
1120 }
1121 else
1122 {
1123 using std::swap;
1124 swap(_M_unex, __x._M_unex);
1125 }
1126 }
1127 }
1128
1129 // observers
1130
1131 [[nodiscard]]
1132 constexpr explicit
1133 operator bool() const noexcept { return _M_has_value; }
1134
1135 [[nodiscard]]
1136 constexpr bool has_value() const noexcept { return _M_has_value; }
1137
1138 constexpr void
1139 operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1140
1141 constexpr void
1142 value() const&
1143 {
1144 if (_M_has_value) [[likely]]
1145 return;
1146 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1147 }
1148
1149 constexpr void
1150 value() &&
1151 {
1152 if (_M_has_value) [[likely]]
1153 return;
1154 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1155 }
1156
1157 constexpr const _Er&
1158 error() const & noexcept
1159 {
1160 __glibcxx_assert(!_M_has_value);
1161 return _M_unex;
1162 }
1163
1164 constexpr _Er&
1165 error() & noexcept
1166 {
1167 __glibcxx_assert(!_M_has_value);
1168 return _M_unex;
1169 }
1170
1171 constexpr const _Er&&
1172 error() const && noexcept
1173 {
1174 __glibcxx_assert(!_M_has_value);
1175 return std::move(_M_unex);
1176 }
1177
1178 constexpr _Er&&
1179 error() && noexcept
1180 {
1181 __glibcxx_assert(!_M_has_value);
1182 return std::move(_M_unex);
1183 }
1184
1185 // equality operators
1186
1187 template<typename _Up, typename _Er2>
1188 requires is_void_v<_Up>
1189 friend constexpr bool
1190 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1191 noexcept(noexcept(bool(__x.error() == __y.error())))
1192 {
1193 if (__x.has_value())
1194 return __y.has_value();
1195 else
1196 return !__y.has_value() && bool(__x.error() == __y.error());
1197 }
1198
1199 template<typename _Er2>
1200 friend constexpr bool
1201 operator==(const expected& __x, const unexpected<_Er2>& __e)
1202 noexcept(noexcept(bool(__x.error() == __e.error())))
1203 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1204
1205 friend constexpr void
1206 swap(expected& __x, expected& __y)
1207 noexcept(noexcept(__x.swap(__y)))
1208 requires requires { __x.swap(__y); }
1209 { __x.swap(__y); }
1210
1211 private:
1212 template<typename, typename> friend class expected;
1213
1214 template<typename _Vp>
1215 constexpr void
1216 _M_assign_unex(_Vp&& __v)
1217 {
1218 if (_M_has_value)
1219 {
1220 std::construct_at(__builtin_addressof(_M_unex),
1221 std::forward<_Vp>(__v));
1222 _M_has_value = false;
1223 }
1224 else
1225 _M_unex = std::forward<_Vp>(__v);
1226 }
1227
1228
1229 union {
1230 struct { } _M_void;
1231 _Er _M_unex;
1232 };
1233
1234 bool _M_has_value;
1235 };
1236 /// @}
1237
1238_GLIBCXX_END_NAMESPACE_VERSION
1239} // namespace std
1240
1241#endif // C++23
1242#endif // _GLIBCXX_EXPECTED