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 requires is_swappable_v<_Er>
221 {
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) noexcept(noexcept(__x.swap(__y)))
234 requires is_swappable_v<_Er>
235 { __x.swap(__y); }
236
237 private:
238 _Er _M_unex;
239 };
240
241 template<typename _Er> unexpected(_Er) -> unexpected<_Er>;
242
243/// @cond undoc
244namespace __expected
245{
246 template<typename _Tp>
247 struct _Guard
248 {
249 static_assert( is_nothrow_move_constructible_v<_Tp> );
250
251 constexpr explicit
252 _Guard(_Tp& __x)
253 : _M_guarded(__builtin_addressof(__x)), _M_tmp(std::move(__x)) // nothrow
254 { std::destroy_at(_M_guarded); }
255
256 constexpr
257 ~_Guard()
258 {
259 if (_M_guarded) [[unlikely]]
260 std::construct_at(_M_guarded, std::move(_M_tmp));
261 }
262
263 _Guard(const _Guard&) = delete;
264 _Guard& operator=(const _Guard&) = delete;
265
266 constexpr _Tp&&
267 release() noexcept
268 {
269 _M_guarded = nullptr;
270 return std::move(_M_tmp);
271 }
272
273 private:
274 _Tp* _M_guarded;
275 _Tp _M_tmp;
276 };
277
278 // reinit-expected helper from [expected.object.assign]
279 template<typename _Tp, typename _Up, typename _Vp>
280 constexpr void
281 __reinit(_Tp* __newval, _Up* __oldval, _Vp&& __arg)
282 noexcept(is_nothrow_constructible_v<_Tp, _Vp>)
283 {
284 if constexpr (is_nothrow_constructible_v<_Tp, _Vp>)
285 {
286 std::destroy_at(__oldval);
287 std::construct_at(__newval, std::forward<_Vp>(__arg));
288 }
289 else if constexpr (is_nothrow_move_constructible_v<_Tp>)
290 {
291 _Tp __tmp(std::forward<_Vp>(__arg)); // might throw
292 std::destroy_at(__oldval);
293 std::construct_at(__newval, std::move(__tmp));
294 }
295 else
296 {
297 _Guard<_Up> __guard(*__oldval);
298 std::construct_at(__newval, std::forward<_Vp>(__arg)); // might throw
299 __guard.release();
300 }
301 }
302}
303/// @endcond
304
305 template<typename _Tp, typename _Er>
306 class expected
307 {
308 static_assert( ! is_reference_v<_Tp> );
309 static_assert( ! is_function_v<_Tp> );
310 static_assert( ! is_same_v<remove_cv_t<_Tp>, in_place_t> );
311 static_assert( ! is_same_v<remove_cv_t<_Tp>, unexpect_t> );
312 static_assert( ! __expected::__is_unexpected<remove_cv_t<_Tp>> );
313 static_assert( __expected::__can_be_unexpected<_Er> );
314
315 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
316 static constexpr bool __cons_from_expected
317 = __or_v<is_constructible<_Tp, expected<_Up, _Err>&>,
318 is_constructible<_Tp, expected<_Up, _Err>>,
319 is_constructible<_Tp, const expected<_Up, _Err>&>,
320 is_constructible<_Tp, const expected<_Up, _Err>>,
321 is_convertible<expected<_Up, _Err>&, _Tp>,
322 is_convertible<expected<_Up, _Err>, _Tp>,
323 is_convertible<const expected<_Up, _Err>&, _Tp>,
324 is_convertible<const expected<_Up, _Err>, _Tp>,
325 is_constructible<_Unex, expected<_Up, _Err>&>,
326 is_constructible<_Unex, expected<_Up, _Err>>,
327 is_constructible<_Unex, const expected<_Up, _Err>&>,
328 is_constructible<_Unex, const expected<_Up, _Err>>
329 >;
330
331 template<typename _Up, typename _Err>
332 constexpr static bool __explicit_conv
333 = __or_v<__not_<is_convertible<_Up, _Tp>>,
334 __not_<is_convertible<_Err, _Er>>
335 >;
336
337 public:
338 using value_type = _Tp;
339 using error_type = _Er;
340 using unexpected_type = unexpected<_Er>;
341
342 template<typename _Up>
343 using rebind = expected<_Up, error_type>;
344
345 constexpr
346 expected()
347 noexcept(is_nothrow_default_constructible_v<_Tp>)
348 requires is_default_constructible_v<_Tp>
349 : _M_val(), _M_has_value(true)
350 { }
351
352 expected(const expected&) = default;
353
354 constexpr
355 expected(const expected& __x)
356 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
357 is_nothrow_copy_constructible<_Er>>)
358 requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er>
359 && (!is_trivially_copy_constructible_v<_Tp>
360 || !is_trivially_copy_constructible_v<_Er>)
361 : _M_has_value(__x._M_has_value)
362 {
363 if (_M_has_value)
364 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
365 else
366 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
367 }
368
369 expected(expected&&) = default;
370
371 constexpr
372 expected(expected&& __x)
373 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
374 is_nothrow_move_constructible<_Er>>)
375 requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er>
376 && (!is_trivially_move_constructible_v<_Tp>
377 || !is_trivially_move_constructible_v<_Er>)
378 : _M_has_value(__x._M_has_value)
379 {
380 if (_M_has_value)
381 std::construct_at(__builtin_addressof(_M_val),
382 std::move(__x)._M_val);
383 else
384 std::construct_at(__builtin_addressof(_M_unex),
385 std::move(__x)._M_unex);
386 }
387
388 template<typename _Up, typename _Gr>
389 requires is_constructible_v<_Tp, const _Up&>
390 && is_constructible_v<_Er, const _Gr&>
391 && (!__cons_from_expected<_Up, _Gr>)
392 constexpr explicit(__explicit_conv<const _Up&, const _Gr&>)
393 expected(const expected<_Up, _Gr>& __x)
394 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>,
395 is_nothrow_constructible<_Er, const _Gr&>>)
396 : _M_has_value(__x._M_has_value)
397 {
398 if (_M_has_value)
399 std::construct_at(__builtin_addressof(_M_val), __x._M_val);
400 else
401 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
402 }
403
404 template<typename _Up, typename _Gr>
405 requires is_constructible_v<_Tp, _Up>
406 && is_constructible_v<_Er, _Gr>
407 && (!__cons_from_expected<_Up, _Gr>)
408 constexpr explicit(__explicit_conv<_Up, _Gr>)
409 expected(expected<_Up, _Gr>&& __x)
410 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>,
411 is_nothrow_constructible<_Er, _Gr>>)
412 : _M_has_value(__x._M_has_value)
413 {
414 if (_M_has_value)
415 std::construct_at(__builtin_addressof(_M_val),
416 std::move(__x)._M_val);
417 else
418 std::construct_at(__builtin_addressof(_M_unex),
419 std::move(__x)._M_unex);
420 }
421
422 template<typename _Up = _Tp>
423 requires (!is_same_v<remove_cvref_t<_Up>, expected>)
424 && (!is_same_v<remove_cvref_t<_Up>, in_place_t>)
425 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
426 && is_constructible_v<_Tp, _Up>
427 constexpr explicit(!is_convertible_v<_Up, _Tp>)
428 expected(_Up&& __v)
429 noexcept(is_nothrow_constructible_v<_Tp, _Up>)
430 : _M_val(std::forward<_Up>(__v)), _M_has_value(true)
431 { }
432
433 template<typename _Gr = _Er>
434 requires is_constructible_v<_Er, const _Gr&>
435 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
436 expected(const unexpected<_Gr>& __u)
437 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
438 : _M_unex(__u.error()), _M_has_value(false)
439 { }
440
441 template<typename _Gr = _Er>
442 requires is_constructible_v<_Er, _Gr>
443 constexpr explicit(!is_convertible_v<_Gr, _Er>)
444 expected(unexpected<_Gr>&& __u)
445 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
446 : _M_unex(std::move(__u).error()), _M_has_value(false)
447 { }
448
449 template<typename... _Args>
450 requires is_constructible_v<_Tp, _Args...>
451 constexpr explicit
452 expected(in_place_t, _Args&&... __args)
453 noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
454 : _M_val(std::forward<_Args>(__args)...), _M_has_value(true)
455 { }
456
457 template<typename _Up, typename... _Args>
458 requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
459 constexpr explicit
460 expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
461 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
462 _Args...>)
463 : _M_val(__il, std::forward<_Args>(__args)...), _M_has_value(true)
464 { }
465
466 template<typename... _Args>
467 requires is_constructible_v<_Er, _Args...>
468 constexpr explicit
469 expected(unexpect_t, _Args&&... __args)
470 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
471 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
472 { }
473
474 template<typename _Up, typename... _Args>
475 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
476 constexpr explicit
477 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
478 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
479 _Args...>)
480 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
481 { }
482
483 constexpr ~expected() = default;
484
485 constexpr ~expected()
486 requires (!is_trivially_destructible_v<_Tp>)
487 || (!is_trivially_destructible_v<_Er>)
488 {
489 if (_M_has_value)
490 std::destroy_at(__builtin_addressof(_M_val));
491 else
492 std::destroy_at(__builtin_addressof(_M_unex));
493 }
494
495 // assignment
496
497 expected& operator=(const expected&) = delete;
498
499 constexpr expected&
500 operator=(const expected& __x)
501 noexcept(__and_v<is_nothrow_copy_constructible<_Tp>,
502 is_nothrow_copy_constructible<_Er>,
503 is_nothrow_copy_assignable<_Tp>,
504 is_nothrow_copy_assignable<_Er>>)
505 requires is_copy_assignable_v<_Tp> && is_copy_constructible_v<_Tp>
506 && is_copy_assignable_v<_Er> && is_copy_constructible_v<_Er>
507 && (is_nothrow_move_constructible_v<_Tp>
508 || is_nothrow_move_constructible_v<_Er>)
509 {
510 if (__x._M_has_value)
511 this->_M_assign_val(__x._M_val);
512 else
513 this->_M_assign_unex(__x._M_unex);
514 return *this;
515 }
516
517 constexpr expected&
518 operator=(expected&& __x)
519 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
520 is_nothrow_move_constructible<_Er>,
521 is_nothrow_move_assignable<_Tp>,
522 is_nothrow_move_assignable<_Er>>)
523 requires is_move_assignable_v<_Tp> && is_move_constructible_v<_Tp>
524 && is_move_assignable_v<_Er> && is_move_constructible_v<_Er>
525 && (is_nothrow_move_constructible_v<_Tp>
526 || is_nothrow_move_constructible_v<_Er>)
527 {
528 if (__x._M_has_value)
529 _M_assign_val(std::move(__x._M_val));
530 else
531 _M_assign_unex(std::move(__x._M_unex));
532 return *this;
533 }
534
535 template<typename _Up = _Tp>
536 requires (!is_same_v<expected, remove_cvref_t<_Up>>)
537 && (!__expected::__is_unexpected<remove_cvref_t<_Up>>)
538 && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up>
539 && (is_nothrow_constructible_v<_Tp, _Up>
540 || is_nothrow_move_constructible_v<_Tp>
541 || is_nothrow_move_constructible_v<_Er>)
542 constexpr expected&
543 operator=(_Up&& __v)
544 {
545 _M_assign_val(std::forward<_Up>(__v));
546 return *this;
547 }
548
549 template<typename _Gr>
550 requires is_constructible_v<_Er, const _Gr&>
551 && is_assignable_v<_Er&, const _Gr&>
552 && (is_nothrow_constructible_v<_Er, const _Gr&>
553 || is_nothrow_move_constructible_v<_Tp>
554 || is_nothrow_move_constructible_v<_Er>)
555 constexpr expected&
556 operator=(const unexpected<_Gr>& __e)
557 {
558 _M_assign_unex(__e.error());
559 return *this;
560 }
561
562 template<typename _Gr>
563 requires is_constructible_v<_Er, _Gr>
564 && is_assignable_v<_Er&, _Gr>
565 && (is_nothrow_constructible_v<_Er, _Gr>
566 || is_nothrow_move_constructible_v<_Tp>
567 || is_nothrow_move_constructible_v<_Er>)
568 constexpr expected&
569 operator=(unexpected<_Gr>&& __e)
570 {
571 _M_assign_unex(std::move(__e).error());
572 return *this;
573 }
574
575 // modifiers
576
577 template<typename... _Args>
578 requires is_nothrow_constructible_v<_Tp, _Args...>
579 constexpr _Tp&
580 emplace(_Args&&... __args) noexcept
581 {
582 if (_M_has_value)
583 std::destroy_at(__builtin_addressof(_M_val));
584 else
585 {
586 std::destroy_at(__builtin_addressof(_M_unex));
587 _M_has_value = true;
588 }
589 std::construct_at(__builtin_addressof(_M_val),
590 std::forward<_Args>(__args)...);
591 return _M_val;
592 }
593
594 template<typename _Up, typename... _Args>
595 requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&,
596 _Args...>
597 constexpr _Tp&
598 emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept
599 {
600 if (_M_has_value)
601 std::destroy_at(__builtin_addressof(_M_val));
602 else
603 {
604 std::destroy_at(__builtin_addressof(_M_unex));
605 _M_has_value = true;
606 }
607 std::construct_at(__builtin_addressof(_M_val),
608 __il, std::forward<_Args>(__args)...);
609 return _M_val;
610 }
611
612 // swap
613 constexpr void
614 swap(expected& __x)
615 noexcept(__and_v<is_nothrow_move_constructible<_Tp>,
616 is_nothrow_move_constructible<_Er>,
617 is_nothrow_swappable<_Tp&>,
618 is_nothrow_swappable<_Er&>>)
619 requires is_swappable_v<_Tp> && is_swappable_v<_Er>
620 && is_move_constructible_v<_Tp>
621 && is_move_constructible_v<_Er>
622 && (is_nothrow_move_constructible_v<_Tp>
623 || is_nothrow_move_constructible_v<_Er>)
624 {
625 if (_M_has_value)
626 {
627 if (__x._M_has_value)
628 {
629 using std::swap;
630 swap(_M_val, __x._M_val);
631 }
632 else
633 this->_M_swap_val_unex(__x);
634 }
635 else
636 {
637 if (__x._M_has_value)
638 __x._M_swap_val_unex(*this);
639 else
640 {
641 using std::swap;
642 swap(_M_unex, __x._M_unex);
643 }
644 }
645 }
646
647 // observers
648
649 [[nodiscard]]
650 constexpr const _Tp*
651 operator->() const noexcept
652 {
653 __glibcxx_assert(_M_has_value);
654 return __builtin_addressof(_M_val);
655 }
656
657 [[nodiscard]]
658 constexpr _Tp*
659 operator->() noexcept
660 {
661 __glibcxx_assert(_M_has_value);
662 return __builtin_addressof(_M_val);
663 }
664
665 [[nodiscard]]
666 constexpr const _Tp&
667 operator*() const & noexcept
668 {
669 __glibcxx_assert(_M_has_value);
670 return _M_val;
671 }
672
673 [[nodiscard]]
674 constexpr _Tp&
675 operator*() & noexcept
676 {
677 __glibcxx_assert(_M_has_value);
678 return _M_val;
679 }
680
681 [[nodiscard]]
682 constexpr const _Tp&&
683 operator*() const && noexcept
684 {
685 __glibcxx_assert(_M_has_value);
686 return std::move(_M_val);
687 }
688
689 [[nodiscard]]
690 constexpr _Tp&&
691 operator*() && noexcept
692 {
693 __glibcxx_assert(_M_has_value);
694 return std::move(_M_val);
695 }
696
697 [[nodiscard]]
698 constexpr explicit
699 operator bool() const noexcept { return _M_has_value; }
700
701 [[nodiscard]]
702 constexpr bool has_value() const noexcept { return _M_has_value; }
703
704 constexpr const _Tp&
705 value() const &
706 {
707 if (_M_has_value) [[likely]]
708 return _M_val;
709 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
710 }
711
712 constexpr _Tp&
713 value() &
714 {
715 if (_M_has_value) [[likely]]
716 return _M_val;
717 const auto& __unex = _M_unex;
718 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(__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 // FIXME: 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 // FIXME: 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 // FIXME: 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(_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 _Tp _M_val;
894 _Er _M_unex;
895 };
896
897 bool _M_has_value;
898 };
899
900 // Partial specialization for std::expected<cv void, E>
901 template<typename _Tp, typename _Er> requires is_void_v<_Tp>
902 class expected<_Tp, _Er>
903 {
904 static_assert( __expected::__can_be_unexpected<_Er> );
905
906 template<typename _Up, typename _Err, typename _Unex = unexpected<_Er>>
907 static constexpr bool __cons_from_expected
908 = __or_v<is_constructible<_Unex, expected<_Up, _Err>&>,
909 is_constructible<_Unex, expected<_Up, _Err>>,
910 is_constructible<_Unex, const expected<_Up, _Err>&>,
911 is_constructible<_Unex, const expected<_Up, _Err>>
912 >;
913
914 public:
915 using value_type = _Tp;
916 using error_type = _Er;
917 using unexpected_type = unexpected<_Er>;
918
919 template<typename _Up>
920 using rebind = expected<_Up, error_type>;
921
922 constexpr
923 expected() noexcept
924 : _M_void(), _M_has_value(true)
925 { }
926
927 expected(const expected&) = default;
928
929 constexpr
930 expected(const expected& __x)
931 noexcept(is_nothrow_copy_constructible_v<_Er>)
932 requires is_copy_constructible_v<_Er>
933 && (!is_trivially_copy_constructible_v<_Er>)
934 : _M_void(), _M_has_value(__x._M_has_value)
935 {
936 if (!_M_has_value)
937 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
938 }
939
940 expected(expected&&) = default;
941
942 constexpr
943 expected(expected&& __x)
944 noexcept(is_nothrow_move_constructible_v<_Er>)
945 requires is_move_constructible_v<_Er>
946 && (!is_trivially_move_constructible_v<_Er>)
947 : _M_void(), _M_has_value(__x._M_has_value)
948 {
949 if (!_M_has_value)
950 std::construct_at(__builtin_addressof(_M_unex),
951 std::move(__x)._M_unex);
952 }
953
954 template<typename _Up, typename _Gr>
955 requires is_void_v<_Up>
956 && is_constructible_v<_Er, const _Gr&>
957 && (!__cons_from_expected<_Up, _Gr>)
958 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
959 expected(const expected<_Up, _Gr>& __x)
960 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
961 : _M_void(), _M_has_value(__x._M_has_value)
962 {
963 if (!_M_has_value)
964 std::construct_at(__builtin_addressof(_M_unex), __x._M_unex);
965 }
966
967 template<typename _Up, typename _Gr>
968 requires is_void_v<_Up>
969 && is_constructible_v<_Er, _Gr>
970 && (!__cons_from_expected<_Up, _Gr>)
971 constexpr explicit(!is_convertible_v<_Gr, _Er>)
972 expected(expected<_Up, _Gr>&& __x)
973 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
974 : _M_void(), _M_has_value(__x._M_has_value)
975 {
976 if (!_M_has_value)
977 std::construct_at(__builtin_addressof(_M_unex),
978 std::move(__x)._M_unex);
979 }
980
981 template<typename _Gr = _Er>
982 requires is_constructible_v<_Er, const _Gr&>
983 constexpr explicit(!is_convertible_v<const _Gr&, _Er>)
984 expected(const unexpected<_Gr>& __u)
985 noexcept(is_nothrow_constructible_v<_Er, const _Gr&>)
986 : _M_unex(__u.error()), _M_has_value(false)
987 { }
988
989 template<typename _Gr = _Er>
990 requires is_constructible_v<_Er, _Gr>
991 constexpr explicit(!is_convertible_v<_Gr, _Er>)
992 expected(unexpected<_Gr>&& __u)
993 noexcept(is_nothrow_constructible_v<_Er, _Gr>)
994 : _M_unex(std::move(__u).error()), _M_has_value(false)
995 { }
996
997 constexpr explicit
998 expected(in_place_t) noexcept
999 : expected()
1000 { }
1001
1002 template<typename... _Args>
1003 requires is_constructible_v<_Er, _Args...>
1004 constexpr explicit
1005 expected(unexpect_t, _Args&&... __args)
1006 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1007 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1008 { }
1009
1010 template<typename _Up, typename... _Args>
1011 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1012 constexpr explicit
1013 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1014 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1015 _Args...>)
1016 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1017 { }
1018
1019 constexpr ~expected() = default;
1020
1021 constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1022 {
1023 if (!_M_has_value)
1024 std::destroy_at(__builtin_addressof(_M_unex));
1025 }
1026
1027 // assignment
1028
1029 expected& operator=(const expected&) = delete;
1030
1031 constexpr expected&
1032 operator=(const expected& __x)
1033 noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1034 is_nothrow_copy_assignable<_Er>>)
1035 requires is_copy_constructible_v<_Er>
1036 && is_copy_assignable_v<_Er>
1037 {
1038 if (__x._M_has_value)
1039 emplace();
1040 else
1041 _M_assign_unex(__x._M_unex);
1042 return *this;
1043 }
1044
1045 constexpr expected&
1046 operator=(expected&& __x)
1047 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1048 is_nothrow_move_assignable<_Er>>)
1049 requires is_move_constructible_v<_Er>
1050 && is_move_assignable_v<_Er>
1051 {
1052 if (__x._M_has_value)
1053 emplace();
1054 else
1055 _M_assign_unex(std::move(__x._M_unex));
1056 return *this;
1057 }
1058
1059 template<typename _Gr>
1060 requires is_constructible_v<_Er, const _Gr&>
1061 && is_assignable_v<_Er&, const _Gr&>
1062 constexpr expected&
1063 operator=(const unexpected<_Gr>& __e)
1064 {
1065 _M_assign_unex(__e.error());
1066 return *this;
1067 }
1068
1069 template<typename _Gr>
1070 requires is_constructible_v<_Er, _Gr>
1071 && is_assignable_v<_Er&, _Gr>
1072 constexpr expected&
1073 operator=(unexpected<_Gr>&& __e)
1074 {
1075 _M_assign_unex(std::move(__e.error()));
1076 return *this;
1077 }
1078
1079 // modifiers
1080
1081 constexpr void
1082 emplace() noexcept
1083 {
1084 if (!_M_has_value)
1085 {
1086 std::destroy_at(__builtin_addressof(_M_unex));
1087 _M_has_value = true;
1088 }
1089 }
1090
1091 // swap
1092 constexpr void
1093 swap(expected& __x)
1094 noexcept(__and_v<is_nothrow_swappable<_Er&>,
1095 is_nothrow_move_constructible<_Er>>)
1096 requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1097 {
1098 if (_M_has_value)
1099 {
1100 if (!__x._M_has_value)
1101 {
1102 std::construct_at(__builtin_addressof(_M_unex),
1103 std::move(__x._M_unex)); // might throw
1104 std::destroy_at(__builtin_addressof(__x._M_unex));
1105 _M_has_value = false;
1106 __x._M_has_value = true;
1107 }
1108 }
1109 else
1110 {
1111 if (__x._M_has_value)
1112 {
1113 std::construct_at(__builtin_addressof(__x._M_unex),
1114 std::move(_M_unex)); // might throw
1115 std::destroy_at(__builtin_addressof(_M_unex));
1116 _M_has_value = true;
1117 __x._M_has_value = false;
1118 }
1119 else
1120 {
1121 using std::swap;
1122 swap(_M_unex, __x._M_unex);
1123 }
1124 }
1125 }
1126
1127 // observers
1128
1129 [[nodiscard]]
1130 constexpr explicit
1131 operator bool() const noexcept { return _M_has_value; }
1132
1133 [[nodiscard]]
1134 constexpr bool has_value() const noexcept { return _M_has_value; }
1135
1136 constexpr void
1137 operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1138
1139 constexpr void
1140 value() const&
1141 {
1142 if (_M_has_value) [[likely]]
1143 return;
1144 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1145 }
1146
1147 constexpr void
1148 value() &&
1149 {
1150 if (_M_has_value) [[likely]]
1151 return;
1152 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1153 }
1154
1155 constexpr const _Er&
1156 error() const & noexcept
1157 {
1158 __glibcxx_assert(!_M_has_value);
1159 return _M_unex;
1160 }
1161
1162 constexpr _Er&
1163 error() & noexcept
1164 {
1165 __glibcxx_assert(!_M_has_value);
1166 return _M_unex;
1167 }
1168
1169 constexpr const _Er&&
1170 error() const && noexcept
1171 {
1172 __glibcxx_assert(!_M_has_value);
1173 return std::move(_M_unex);
1174 }
1175
1176 constexpr _Er&&
1177 error() && noexcept
1178 {
1179 __glibcxx_assert(!_M_has_value);
1180 return std::move(_M_unex);
1181 }
1182
1183 // equality operators
1184
1185 template<typename _Up, typename _Er2>
1186 requires is_void_v<_Up>
1187 friend constexpr bool
1188 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1189 // FIXME: noexcept(noexcept(bool(__x.error() == __y.error())))
1190 {
1191 if (__x.has_value())
1192 return __y.has_value();
1193 else
1194 return !__y.has_value() && bool(__x.error() == __y.error());
1195 }
1196
1197 template<typename _Er2>
1198 friend constexpr bool
1199 operator==(const expected& __x, const unexpected<_Er2>& __e)
1200 // FIXME: noexcept(noexcept(bool(__x.error() == __e.error())))
1201 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1202
1203 friend constexpr void
1204 swap(expected& __x, expected& __y)
1205 noexcept(noexcept(__x.swap(__y)))
1206 requires requires { __x.swap(__y); }
1207 { __x.swap(__y); }
1208
1209 private:
1210 template<typename, typename> friend class expected;
1211
1212 template<typename _Vp>
1213 constexpr void
1214 _M_assign_unex(_Vp&& __v)
1215 {
1216 if (_M_has_value)
1217 {
1218 std::construct_at(__builtin_addressof(_M_unex),
1219 std::forward<_Vp>(__v));
1220 _M_has_value = false;
1221 }
1222 else
1223 _M_unex = std::forward<_Vp>(__v);
1224 }
1225
1226
1227 union {
1228 struct { } _M_void;
1229 _Er _M_unex;
1230 };
1231
1232 bool _M_has_value;
1233 };
1234 /// @}
1235
1236_GLIBCXX_END_NAMESPACE_VERSION
1237} // namespace std
1238
1239#endif // C++23
1240#endif // _GLIBCXX_EXPECTED