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_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_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_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_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 _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 template<typename... _Args>
998 constexpr explicit
999 expected(in_place_t) noexcept
1000 : expected()
1001 { }
1002
1003 template<typename... _Args>
1004 requires is_constructible_v<_Er, _Args...>
1005 constexpr explicit
1006 expected(unexpect_t, _Args&&... __args)
1007 noexcept(is_nothrow_constructible_v<_Er, _Args...>)
1008 : _M_unex(std::forward<_Args>(__args)...), _M_has_value(false)
1009 { }
1010
1011 template<typename _Up, typename... _Args>
1012 requires is_constructible_v<_Er, initializer_list<_Up>&, _Args...>
1013 constexpr explicit
1014 expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
1015 noexcept(is_nothrow_constructible_v<_Er, initializer_list<_Up>&,
1016 _Args...>)
1017 : _M_unex(__il, std::forward<_Args>(__args)...), _M_has_value(false)
1018 { }
1019
1020 constexpr ~expected() = default;
1021
1022 constexpr ~expected() requires (!is_trivially_destructible_v<_Er>)
1023 {
1024 if (!_M_has_value)
1025 std::destroy_at(__builtin_addressof(_M_unex));
1026 }
1027
1028 // assignment
1029
1030 expected& operator=(const expected&) = delete;
1031
1032 constexpr expected&
1033 operator=(const expected& __x)
1034 noexcept(__and_v<is_nothrow_copy_constructible<_Er>,
1035 is_nothrow_copy_assignable<_Er>>)
1036 requires is_copy_constructible_v<_Er>
1037 && is_copy_assignable_v<_Er>
1038 {
1039 if (__x._M_has_value)
1040 emplace();
1041 else
1042 _M_assign_unex(__x._M_unex);
1043 return *this;
1044 }
1045
1046 constexpr expected&
1047 operator=(expected&& __x)
1048 noexcept(__and_v<is_nothrow_move_constructible<_Er>,
1049 is_nothrow_move_assignable<_Er>>)
1050 requires is_move_constructible_v<_Er>
1051 && is_move_assignable_v<_Er>
1052 {
1053 if (__x._M_has_value)
1054 emplace();
1055 else
1056 _M_assign_unex(std::move(__x._M_unex));
1057 return *this;
1058 }
1059
1060 template<typename _Gr>
1061 requires is_constructible_v<_Er, const _Gr&>
1062 && is_assignable_v<_Er&, const _Gr&>
1063 constexpr expected&
1064 operator=(const unexpected<_Gr>& __e)
1065 {
1066 _M_assign_unex(__e.error());
1067 return *this;
1068 }
1069
1070 template<typename _Gr>
1071 requires is_constructible_v<_Er, _Gr>
1072 && is_assignable_v<_Er&, _Gr>
1073 constexpr expected&
1074 operator=(unexpected<_Gr>&& __e)
1075 {
1076 _M_assign_unex(std::move(__e.error()));
1077 return *this;
1078 }
1079
1080 // modifiers
1081
1082 constexpr void
1083 emplace() noexcept
1084 {
1085 if (!_M_has_value)
1086 {
1087 std::destroy_at(__builtin_addressof(_M_unex));
1088 _M_has_value = true;
1089 }
1090 }
1091
1092 // swap
1093 constexpr void
1094 swap(expected& __x)
1095 noexcept(__and_v<is_nothrow_swappable<_Er&>,
1096 is_nothrow_move_constructible<_Er>>)
1097 requires is_swappable_v<_Er> && is_move_constructible_v<_Er>
1098 {
1099 if (_M_has_value)
1100 {
1101 if (!__x._M_has_value)
1102 {
1103 std::construct_at(__builtin_addressof(_M_unex),
1104 std::move(__x._M_unex)); // might throw
1105 std::destroy_at(__builtin_addressof(__x._M_unex));
1106 _M_has_value = false;
1107 __x._M_has_value = true;
1108 }
1109 }
1110 else
1111 {
1112 if (__x._M_has_value)
1113 {
1114 std::construct_at(__builtin_addressof(__x._M_unex),
1115 std::move(_M_unex)); // might throw
1116 std::destroy_at(__builtin_addressof(_M_unex));
1117 _M_has_value = true;
1118 __x._M_has_value = false;
1119 }
1120 else
1121 {
1122 using std::swap;
1123 swap(_M_unex, __x._M_unex);
1124 }
1125 }
1126 }
1127
1128 // observers
1129
1130 [[nodiscard]]
1131 constexpr explicit
1132 operator bool() const noexcept { return _M_has_value; }
1133
1134 [[nodiscard]]
1135 constexpr bool has_value() const noexcept { return _M_has_value; }
1136
1137 constexpr void
1138 operator*() const noexcept { __glibcxx_assert(_M_has_value); }
1139
1140 constexpr void
1141 value() const&
1142 {
1143 if (_M_has_value) [[likely]]
1144 return;
1145 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(_M_unex));
1146 }
1147
1148 constexpr void
1149 value() &&
1150 {
1151 if (_M_has_value) [[likely]]
1152 return;
1153 _GLIBCXX_THROW_OR_ABORT(bad_expected_access<_Er>(std::move(_M_unex)));
1154 }
1155
1156 constexpr const _Er&
1157 error() const & noexcept
1158 {
1159 __glibcxx_assert(!_M_has_value);
1160 return _M_unex;
1161 }
1162
1163 constexpr _Er&
1164 error() & noexcept
1165 {
1166 __glibcxx_assert(!_M_has_value);
1167 return _M_unex;
1168 }
1169
1170 constexpr const _Er&&
1171 error() const && noexcept
1172 {
1173 __glibcxx_assert(!_M_has_value);
1174 return std::move(_M_unex);
1175 }
1176
1177 constexpr _Er&&
1178 error() && noexcept
1179 {
1180 __glibcxx_assert(!_M_has_value);
1181 return std::move(_M_unex);
1182 }
1183
1184 // equality operators
1185
1186 template<typename _Up, typename _Er2>
1187 requires is_void_v<_Up>
1188 friend constexpr bool
1189 operator==(const expected& __x, const expected<_Up, _Er2>& __y)
1190 noexcept(noexcept(bool(__x.error() == __y.error())))
1191 {
1192 if (__x.has_value())
1193 return __y.has_value();
1194 else
1195 return !__y.has_value() && bool(__x.error() == __y.error());
1196 }
1197
1198 template<typename _Er2>
1199 friend constexpr bool
1200 operator==(const expected& __x, const unexpected<_Er2>& __e)
1201 noexcept(noexcept(bool(__x.error() == __e.error())))
1202 { return !__x.has_value() && bool(__x.error() == __e.error()); }
1203
1204 friend constexpr void
1205 swap(expected& __x, expected& __y)
1206 noexcept(noexcept(__x.swap(__y)))
1207 requires requires { __x.swap(__y); }
1208 { __x.swap(__y); }
1209
1210 private:
1211 template<typename, typename> friend class expected;
1212
1213 template<typename _Vp>
1214 constexpr void
1215 _M_assign_unex(_Vp&& __v)
1216 {
1217 if (_M_has_value)
1218 {
1219 std::construct_at(__builtin_addressof(_M_unex),
1220 std::forward<_Vp>(__v));
1221 _M_has_value = false;
1222 }
1223 else
1224 _M_unex = std::forward<_Vp>(__v);
1225 }
1226
1227
1228 union {
1229 struct { } _M_void;
1230 _Er _M_unex;
1231 };
1232
1233 bool _M_has_value;
1234 };
1235 /// @}
1236
1237_GLIBCXX_END_NAMESPACE_VERSION
1238} // namespace std
1239
1240#endif // C++23
1241#endif // _GLIBCXX_EXPECTED
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
Definition: complex:395
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:104
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition: any:429
void unexpected()
ISO C++ entities toplevel namespace is std.