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