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