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