1 // <optional> -*- C++ -*- 2 3 // Copyright (C) 2013-2024 Free Software Foundation, Inc. 4 // Copyright The GNU Toolchain Authors. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 /** @file include/optional 27 * This is a Standard C++ Library header. 28 */ 29 30 #ifndef _GLIBCXX_OPTIONAL 31 #define _GLIBCXX_OPTIONAL 1 32 33 #pragma GCC system_header 34 35 #define __glibcxx_want_freestanding_optional 36 #define __glibcxx_want_optional 37 #include <bits/version.h> 38 39 #ifdef __cpp_lib_optional // C++ >= 17 40 41 #include <type_traits> 42 #include <exception> 43 #include <new> 44 #include <initializer_list> 45 #include <bits/enable_special_members.h> 46 #include <bits/exception_defines.h> 47 #include <bits/functional_hash.h> 48 #include <bits/stl_construct.h> // _Construct 49 #include <bits/utility.h> // in_place_t 50 #if __cplusplus > 201703L 51 # include <compare> 52 # include <bits/invoke.h> // std::__invoke 53 #endif 54 #if __cplusplus > 202002L 55 # include <concepts> 56 #endif 57 58 namespace std _GLIBCXX_VISIBILITY(default) 59 { 60 _GLIBCXX_BEGIN_NAMESPACE_VERSION 61 62 /** 63 * @addtogroup utilities 64 * @{ 65 */ 66 67 template<typename _Tp> 68 class optional; 69 70 /// Tag type to disengage optional objects. 71 struct nullopt_t 72 { 73 // Do not user-declare default constructor at all for 74 // optional_value = {} syntax to work. 75 // nullopt_t() = delete; 76 77 // Used for constructing nullopt. 78 enum class _Construct { _Token }; 79 80 // Must be constexpr for nullopt_t to be literal. 81 explicit constexpr nullopt_t(_Construct) noexcept { } 82 }; 83 84 /// Tag to disengage optional objects. 85 inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 86 87 template<typename _Fn> struct _Optional_func { _Fn& _M_f; }; 88 89 /** 90 * @brief Exception class thrown when a disengaged optional object is 91 * dereferenced. 92 * @ingroup exceptions 93 */ 94 class bad_optional_access : public exception 95 { 96 public: 97 bad_optional_access() = default; 98 virtual ~bad_optional_access() = default; 99 100 const char* what() const noexcept override 101 { return "bad optional access"; } 102 }; 103 104 // XXX Does not belong here. 105 [[__noreturn__]] inline void 106 __throw_bad_optional_access() 107 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access()); } 108 109 // This class template manages construction/destruction of 110 // the contained value for a std::optional. 111 template <typename _Tp> 112 struct _Optional_payload_base 113 { 114 using _Stored_type = remove_const_t<_Tp>; 115 116 _Optional_payload_base() = default; 117 ~_Optional_payload_base() = default; 118 119 template<typename... _Args> 120 constexpr 121 _Optional_payload_base(in_place_t __tag, _Args&&... __args) 122 : _M_payload(__tag, std::forward<_Args>(__args)...), 123 _M_engaged(true) 124 { } 125 126 template<typename _Up, typename... _Args> 127 constexpr 128 _Optional_payload_base(std::initializer_list<_Up> __il, 129 _Args&&... __args) 130 : _M_payload(__il, std::forward<_Args>(__args)...), 131 _M_engaged(true) 132 { } 133 134 // Constructor used by _Optional_base copy constructor when the 135 // contained value is not trivially copy constructible. 136 constexpr 137 _Optional_payload_base(bool /* __engaged */, 138 const _Optional_payload_base& __other) 139 { 140 if (__other._M_engaged) 141 this->_M_construct(__other._M_get()); 142 } 143 144 // Constructor used by _Optional_base move constructor when the 145 // contained value is not trivially move constructible. 146 constexpr 147 _Optional_payload_base(bool /* __engaged */, 148 _Optional_payload_base&& __other) 149 { 150 if (__other._M_engaged) 151 this->_M_construct(std::move(__other._M_get())); 152 } 153 154 // Copy constructor is only used to when the contained value is 155 // trivially copy constructible. 156 _Optional_payload_base(const _Optional_payload_base&) = default; 157 158 // Move constructor is only used to when the contained value is 159 // trivially copy constructible. 160 _Optional_payload_base(_Optional_payload_base&&) = default; 161 162 _Optional_payload_base& 163 operator=(const _Optional_payload_base&) = default; 164 165 _Optional_payload_base& 166 operator=(_Optional_payload_base&&) = default; 167 168 // used to perform non-trivial copy assignment. 169 constexpr void 170 _M_copy_assign(const _Optional_payload_base& __other) 171 { 172 if (this->_M_engaged && __other._M_engaged) 173 this->_M_get() = __other._M_get(); 174 else 175 { 176 if (__other._M_engaged) 177 this->_M_construct(__other._M_get()); 178 else 179 this->_M_reset(); 180 } 181 } 182 183 // used to perform non-trivial move assignment. 184 constexpr void 185 _M_move_assign(_Optional_payload_base&& __other) 186 noexcept(__and_v<is_nothrow_move_constructible<_Tp>, 187 is_nothrow_move_assignable<_Tp>>) 188 { 189 if (this->_M_engaged && __other._M_engaged) 190 this->_M_get() = std::move(__other._M_get()); 191 else 192 { 193 if (__other._M_engaged) 194 this->_M_construct(std::move(__other._M_get())); 195 else 196 this->_M_reset(); 197 } 198 } 199 200 struct _Empty_byte { }; 201 202 template<typename _Up, bool = is_trivially_destructible_v<_Up>> 203 union _Storage 204 { 205 constexpr _Storage() noexcept : _M_empty() { } 206 207 template<typename... _Args> 208 constexpr 209 _Storage(in_place_t, _Args&&... __args) 210 : _M_value(std::forward<_Args>(__args)...) 211 { } 212 213 template<typename _Vp, typename... _Args> 214 constexpr 215 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) 216 : _M_value(__il, std::forward<_Args>(__args)...) 217 { } 218 219 #if __cplusplus >= 202002L 220 template<typename _Fn, typename _Arg> 221 constexpr 222 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) 223 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), 224 std::forward<_Arg>(__arg))) 225 { } 226 #endif 227 228 _Empty_byte _M_empty; 229 _Up _M_value; 230 }; 231 232 template<typename _Up> 233 union _Storage<_Up, false> 234 { 235 constexpr _Storage() noexcept : _M_empty() { } 236 237 template<typename... _Args> 238 constexpr 239 _Storage(in_place_t, _Args&&... __args) 240 : _M_value(std::forward<_Args>(__args)...) 241 { } 242 243 template<typename _Vp, typename... _Args> 244 constexpr 245 _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) 246 : _M_value(__il, std::forward<_Args>(__args)...) 247 { } 248 249 #if __cplusplus >= 202002L 250 template<typename _Fn, typename _Arg> 251 constexpr 252 _Storage(_Optional_func<_Fn> __f, _Arg&& __arg) 253 : _M_value(std::__invoke(std::forward<_Fn>(__f._M_f), 254 std::forward<_Arg>(__arg))) 255 { } 256 #endif 257 258 // User-provided destructor is needed when _Up has non-trivial dtor. 259 _GLIBCXX20_CONSTEXPR ~_Storage() { } 260 261 _Empty_byte _M_empty; 262 _Up _M_value; 263 }; 264 265 _Storage<_Stored_type> _M_payload; 266 267 bool _M_engaged = false; 268 269 template<typename... _Args> 270 constexpr void 271 _M_construct(_Args&&... __args) 272 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) 273 { 274 std::_Construct(std::__addressof(this->_M_payload._M_value), 275 std::forward<_Args>(__args)...); 276 this->_M_engaged = true; 277 } 278 279 constexpr void 280 _M_destroy() noexcept 281 { 282 _M_engaged = false; 283 _M_payload._M_value.~_Stored_type(); 284 } 285 286 #if __cplusplus >= 202002L 287 template<typename _Fn, typename _Up> 288 constexpr void 289 _M_apply(_Optional_func<_Fn> __f, _Up&& __x) 290 { 291 std::construct_at(std::__addressof(this->_M_payload), 292 __f, std::forward<_Up>(__x)); 293 _M_engaged = true; 294 } 295 #endif 296 297 // The _M_get() operations have _M_engaged as a precondition. 298 // They exist to access the contained value with the appropriate 299 // const-qualification, because _M_payload has had the const removed. 300 301 constexpr _Tp& 302 _M_get() noexcept 303 { return this->_M_payload._M_value; } 304 305 constexpr const _Tp& 306 _M_get() const noexcept 307 { return this->_M_payload._M_value; } 308 309 // _M_reset is a 'safe' operation with no precondition. 310 constexpr void 311 _M_reset() noexcept 312 { 313 if (this->_M_engaged) 314 _M_destroy(); 315 else // This seems redundant but improves codegen, see PR 112480. 316 this->_M_engaged = false; 317 } 318 }; 319 320 // Class template that manages the payload for optionals. 321 template <typename _Tp, 322 bool /*_HasTrivialDestructor*/ = 323 is_trivially_destructible_v<_Tp>, 324 bool /*_HasTrivialCopy */ = 325 is_trivially_copy_assignable_v<_Tp> 326 && is_trivially_copy_constructible_v<_Tp>, 327 bool /*_HasTrivialMove */ = 328 is_trivially_move_assignable_v<_Tp> 329 && is_trivially_move_constructible_v<_Tp>> 330 struct _Optional_payload; 331 332 // Payload for potentially-constexpr optionals (trivial copy/move/destroy). 333 template <typename _Tp> 334 struct _Optional_payload<_Tp, true, true, true> 335 : _Optional_payload_base<_Tp> 336 { 337 using _Optional_payload_base<_Tp>::_Optional_payload_base; 338 339 _Optional_payload() = default; 340 }; 341 342 // Payload for optionals with non-trivial copy construction/assignment. 343 template <typename _Tp> 344 struct _Optional_payload<_Tp, true, false, true> 345 : _Optional_payload_base<_Tp> 346 { 347 using _Optional_payload_base<_Tp>::_Optional_payload_base; 348 349 _Optional_payload() = default; 350 ~_Optional_payload() = default; 351 _Optional_payload(const _Optional_payload&) = default; 352 _Optional_payload(_Optional_payload&&) = default; 353 _Optional_payload& operator=(_Optional_payload&&) = default; 354 355 // Non-trivial copy assignment. 356 constexpr 357 _Optional_payload& 358 operator=(const _Optional_payload& __other) 359 { 360 this->_M_copy_assign(__other); 361 return *this; 362 } 363 }; 364 365 // Payload for optionals with non-trivial move construction/assignment. 366 template <typename _Tp> 367 struct _Optional_payload<_Tp, true, true, false> 368 : _Optional_payload_base<_Tp> 369 { 370 using _Optional_payload_base<_Tp>::_Optional_payload_base; 371 372 _Optional_payload() = default; 373 ~_Optional_payload() = default; 374 _Optional_payload(const _Optional_payload&) = default; 375 _Optional_payload(_Optional_payload&&) = default; 376 _Optional_payload& operator=(const _Optional_payload&) = default; 377 378 // Non-trivial move assignment. 379 constexpr 380 _Optional_payload& 381 operator=(_Optional_payload&& __other) 382 noexcept(__and_v<is_nothrow_move_constructible<_Tp>, 383 is_nothrow_move_assignable<_Tp>>) 384 { 385 this->_M_move_assign(std::move(__other)); 386 return *this; 387 } 388 }; 389 390 // Payload for optionals with non-trivial copy and move assignment. 391 template <typename _Tp> 392 struct _Optional_payload<_Tp, true, false, false> 393 : _Optional_payload_base<_Tp> 394 { 395 using _Optional_payload_base<_Tp>::_Optional_payload_base; 396 397 _Optional_payload() = default; 398 ~_Optional_payload() = default; 399 _Optional_payload(const _Optional_payload&) = default; 400 _Optional_payload(_Optional_payload&&) = default; 401 402 // Non-trivial copy assignment. 403 constexpr 404 _Optional_payload& 405 operator=(const _Optional_payload& __other) 406 { 407 this->_M_copy_assign(__other); 408 return *this; 409 } 410 411 // Non-trivial move assignment. 412 constexpr 413 _Optional_payload& 414 operator=(_Optional_payload&& __other) 415 noexcept(__and_v<is_nothrow_move_constructible<_Tp>, 416 is_nothrow_move_assignable<_Tp>>) 417 { 418 this->_M_move_assign(std::move(__other)); 419 return *this; 420 } 421 }; 422 423 // Payload for optionals with non-trivial destructors. 424 template <typename _Tp, bool _Copy, bool _Move> 425 struct _Optional_payload<_Tp, false, _Copy, _Move> 426 : _Optional_payload<_Tp, true, false, false> 427 { 428 // Base class implements all the constructors and assignment operators: 429 using _Optional_payload<_Tp, true, false, false>::_Optional_payload; 430 _Optional_payload() = default; 431 _Optional_payload(const _Optional_payload&) = default; 432 _Optional_payload(_Optional_payload&&) = default; 433 _Optional_payload& operator=(const _Optional_payload&) = default; 434 _Optional_payload& operator=(_Optional_payload&&) = default; 435 436 // Destructor needs to destroy the contained value: 437 _GLIBCXX20_CONSTEXPR ~_Optional_payload() { this->_M_reset(); } 438 }; 439 440 // Common base class for _Optional_base<T> to avoid repeating these 441 // member functions in each specialization. 442 template<typename _Tp, typename _Dp> 443 class _Optional_base_impl 444 { 445 protected: 446 using _Stored_type = remove_const_t<_Tp>; 447 448 // The _M_construct operation has !_M_engaged as a precondition 449 // while _M_destruct has _M_engaged as a precondition. 450 template<typename... _Args> 451 constexpr void 452 _M_construct(_Args&&... __args) 453 noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) 454 { 455 static_cast<_Dp*>(this)->_M_payload._M_construct( 456 std::forward<_Args>(__args)...); 457 } 458 459 constexpr void 460 _M_destruct() noexcept 461 { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } 462 463 // _M_reset is a 'safe' operation with no precondition. 464 constexpr void 465 _M_reset() noexcept 466 { static_cast<_Dp*>(this)->_M_payload._M_reset(); } 467 468 constexpr bool _M_is_engaged() const noexcept 469 { return static_cast<const _Dp*>(this)->_M_payload._M_engaged; } 470 471 // The _M_get operations have _M_engaged as a precondition. 472 constexpr _Tp& 473 _M_get() noexcept 474 { 475 __glibcxx_assert(this->_M_is_engaged()); 476 return static_cast<_Dp*>(this)->_M_payload._M_get(); 477 } 478 479 constexpr const _Tp& 480 _M_get() const noexcept 481 { 482 __glibcxx_assert(this->_M_is_engaged()); 483 return static_cast<const _Dp*>(this)->_M_payload._M_get(); 484 } 485 }; 486 487 /** 488 * @brief Class template that provides copy/move constructors of optional. 489 * 490 * Such a separate base class template is necessary in order to 491 * conditionally make copy/move constructors trivial. 492 * 493 * When the contained value is trivially copy/move constructible, 494 * the copy/move constructors of _Optional_base will invoke the 495 * trivial copy/move constructor of _Optional_payload. Otherwise, 496 * they will invoke _Optional_payload(bool, const _Optional_payload&) 497 * or _Optional_payload(bool, _Optional_payload&&) to initialize 498 * the contained value, if copying/moving an engaged optional. 499 * 500 * Whether the other special members are trivial is determined by the 501 * _Optional_payload<_Tp> specialization used for the _M_payload member. 502 * 503 * @see optional, _Enable_special_members 504 */ 505 template<typename _Tp, 506 bool = is_trivially_copy_constructible_v<_Tp>, 507 bool = is_trivially_move_constructible_v<_Tp>> 508 struct _Optional_base 509 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 510 { 511 // Constructors for disengaged optionals. 512 constexpr _Optional_base() = default; 513 514 // Constructors for engaged optionals. 515 template<typename... _Args, 516 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 517 constexpr explicit 518 _Optional_base(in_place_t, _Args&&... __args) 519 : _M_payload(in_place, std::forward<_Args>(__args)...) 520 { } 521 522 template<typename _Up, typename... _Args, 523 enable_if_t<is_constructible_v<_Tp, 524 initializer_list<_Up>&, 525 _Args...>, bool> = false> 526 constexpr explicit 527 _Optional_base(in_place_t, 528 initializer_list<_Up> __il, 529 _Args&&... __args) 530 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 531 { } 532 533 // Copy and move constructors. 534 constexpr 535 _Optional_base(const _Optional_base& __other) 536 : _M_payload(__other._M_payload._M_engaged, __other._M_payload) 537 { } 538 539 constexpr 540 _Optional_base(_Optional_base&& __other) 541 noexcept(is_nothrow_move_constructible_v<_Tp>) 542 : _M_payload(__other._M_payload._M_engaged, 543 std::move(__other._M_payload)) 544 { } 545 546 // Assignment operators. 547 _Optional_base& operator=(const _Optional_base&) = default; 548 _Optional_base& operator=(_Optional_base&&) = default; 549 550 _Optional_payload<_Tp> _M_payload; 551 }; 552 553 template<typename _Tp> 554 struct _Optional_base<_Tp, false, true> 555 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 556 { 557 // Constructors for disengaged optionals. 558 constexpr _Optional_base() = default; 559 560 // Constructors for engaged optionals. 561 template<typename... _Args, 562 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 563 constexpr explicit 564 _Optional_base(in_place_t, _Args&&... __args) 565 : _M_payload(in_place, std::forward<_Args>(__args)...) 566 { } 567 568 template<typename _Up, typename... _Args, 569 enable_if_t<is_constructible_v<_Tp, 570 initializer_list<_Up>&, 571 _Args...>, bool> = false> 572 constexpr explicit 573 _Optional_base(in_place_t, 574 initializer_list<_Up> __il, 575 _Args... __args) 576 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 577 { } 578 579 // Copy and move constructors. 580 constexpr _Optional_base(const _Optional_base& __other) 581 : _M_payload(__other._M_payload._M_engaged, __other._M_payload) 582 { } 583 584 constexpr _Optional_base(_Optional_base&& __other) = default; 585 586 // Assignment operators. 587 _Optional_base& operator=(const _Optional_base&) = default; 588 _Optional_base& operator=(_Optional_base&&) = default; 589 590 _Optional_payload<_Tp> _M_payload; 591 }; 592 593 template<typename _Tp> 594 struct _Optional_base<_Tp, true, false> 595 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 596 { 597 // Constructors for disengaged optionals. 598 constexpr _Optional_base() = default; 599 600 // Constructors for engaged optionals. 601 template<typename... _Args, 602 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 603 constexpr explicit 604 _Optional_base(in_place_t, _Args&&... __args) 605 : _M_payload(in_place, std::forward<_Args>(__args)...) 606 { } 607 608 template<typename _Up, typename... _Args, 609 enable_if_t<is_constructible_v<_Tp, 610 initializer_list<_Up>&, 611 _Args...>, bool> = false> 612 constexpr explicit 613 _Optional_base(in_place_t, 614 initializer_list<_Up> __il, 615 _Args&&... __args) 616 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 617 { } 618 619 // Copy and move constructors. 620 constexpr _Optional_base(const _Optional_base& __other) = default; 621 622 constexpr 623 _Optional_base(_Optional_base&& __other) 624 noexcept(is_nothrow_move_constructible_v<_Tp>) 625 : _M_payload(__other._M_payload._M_engaged, 626 std::move(__other._M_payload)) 627 { } 628 629 // Assignment operators. 630 _Optional_base& operator=(const _Optional_base&) = default; 631 _Optional_base& operator=(_Optional_base&&) = default; 632 633 _Optional_payload<_Tp> _M_payload; 634 }; 635 636 template<typename _Tp> 637 struct _Optional_base<_Tp, true, true> 638 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 639 { 640 // Constructors for disengaged optionals. 641 constexpr _Optional_base() = default; 642 643 // Constructors for engaged optionals. 644 template<typename... _Args, 645 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 646 constexpr explicit 647 _Optional_base(in_place_t, _Args&&... __args) 648 : _M_payload(in_place, std::forward<_Args>(__args)...) 649 { } 650 651 template<typename _Up, typename... _Args, 652 enable_if_t<is_constructible_v<_Tp, 653 initializer_list<_Up>&, 654 _Args...>, bool> = false> 655 constexpr explicit 656 _Optional_base(in_place_t, 657 initializer_list<_Up> __il, 658 _Args&&... __args) 659 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 660 { } 661 662 // Copy and move constructors. 663 constexpr _Optional_base(const _Optional_base& __other) = default; 664 constexpr _Optional_base(_Optional_base&& __other) = default; 665 666 // Assignment operators. 667 _Optional_base& operator=(const _Optional_base&) = default; 668 _Optional_base& operator=(_Optional_base&&) = default; 669 670 _Optional_payload<_Tp> _M_payload; 671 }; 672 673 template<typename _Tp> 674 class optional; 675 676 template<typename _Tp> 677 inline constexpr bool __is_optional_v = false; 678 template<typename _Tp> 679 inline constexpr bool __is_optional_v<optional<_Tp>> = true; 680 681 template<typename _Tp, typename _Up> 682 using __converts_from_optional = 683 __or_<is_constructible<_Tp, const optional<_Up>&>, 684 is_constructible<_Tp, optional<_Up>&>, 685 is_constructible<_Tp, const optional<_Up>&&>, 686 is_constructible<_Tp, optional<_Up>&&>, 687 is_convertible<const optional<_Up>&, _Tp>, 688 is_convertible<optional<_Up>&, _Tp>, 689 is_convertible<const optional<_Up>&&, _Tp>, 690 is_convertible<optional<_Up>&&, _Tp>>; 691 692 template<typename _Tp, typename _Up> 693 using __assigns_from_optional = 694 __or_<is_assignable<_Tp&, const optional<_Up>&>, 695 is_assignable<_Tp&, optional<_Up>&>, 696 is_assignable<_Tp&, const optional<_Up>&&>, 697 is_assignable<_Tp&, optional<_Up>&&>>; 698 699 /** 700 * @brief Class template for optional values. 701 */ 702 template<typename _Tp> 703 class optional 704 : private _Optional_base<_Tp>, 705 private _Enable_copy_move< 706 // Copy constructor. 707 is_copy_constructible_v<_Tp>, 708 // Copy assignment. 709 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>, 710 // Move constructor. 711 is_move_constructible_v<_Tp>, 712 // Move assignment. 713 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>, 714 // Unique tag type. 715 optional<_Tp>> 716 { 717 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>); 718 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>); 719 static_assert(is_object_v<_Tp> && !is_array_v<_Tp>); 720 721 private: 722 using _Base = _Optional_base<_Tp>; 723 724 // SFINAE helpers 725 template<typename _Up> 726 using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>; 727 template<typename _Up> 728 using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>; 729 template<typename... _Cond> 730 using _Requires = enable_if_t<__and_v<_Cond...>, bool>; 731 732 public: 733 using value_type = _Tp; 734 735 constexpr optional() noexcept { } 736 737 constexpr optional(nullopt_t) noexcept { } 738 739 // Converting constructors for engaged optionals. 740 template<typename _Up = _Tp, 741 _Requires<__not_self<_Up>, __not_tag<_Up>, 742 is_constructible<_Tp, _Up>, 743 is_convertible<_Up, _Tp>> = true> 744 constexpr 745 optional(_Up&& __t) 746 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 747 : _Base(std::in_place, std::forward<_Up>(__t)) { } 748 749 template<typename _Up = _Tp, 750 _Requires<__not_self<_Up>, __not_tag<_Up>, 751 is_constructible<_Tp, _Up>, 752 __not_<is_convertible<_Up, _Tp>>> = false> 753 explicit constexpr 754 optional(_Up&& __t) 755 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 756 : _Base(std::in_place, std::forward<_Up>(__t)) { } 757 758 template<typename _Up, 759 _Requires<__not_<is_same<_Tp, _Up>>, 760 is_constructible<_Tp, const _Up&>, 761 is_convertible<const _Up&, _Tp>, 762 __not_<__converts_from_optional<_Tp, _Up>>> = true> 763 constexpr 764 optional(const optional<_Up>& __t) 765 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) 766 { 767 if (__t) 768 emplace(*__t); 769 } 770 771 template<typename _Up, 772 _Requires<__not_<is_same<_Tp, _Up>>, 773 is_constructible<_Tp, const _Up&>, 774 __not_<is_convertible<const _Up&, _Tp>>, 775 __not_<__converts_from_optional<_Tp, _Up>>> = false> 776 explicit constexpr 777 optional(const optional<_Up>& __t) 778 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) 779 { 780 if (__t) 781 emplace(*__t); 782 } 783 784 template<typename _Up, 785 _Requires<__not_<is_same<_Tp, _Up>>, 786 is_constructible<_Tp, _Up>, 787 is_convertible<_Up, _Tp>, 788 __not_<__converts_from_optional<_Tp, _Up>>> = true> 789 constexpr 790 optional(optional<_Up>&& __t) 791 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 792 { 793 if (__t) 794 emplace(std::move(*__t)); 795 } 796 797 template<typename _Up, 798 _Requires<__not_<is_same<_Tp, _Up>>, 799 is_constructible<_Tp, _Up>, 800 __not_<is_convertible<_Up, _Tp>>, 801 __not_<__converts_from_optional<_Tp, _Up>>> = false> 802 explicit constexpr 803 optional(optional<_Up>&& __t) 804 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 805 { 806 if (__t) 807 emplace(std::move(*__t)); 808 } 809 810 template<typename... _Args, 811 _Requires<is_constructible<_Tp, _Args...>> = false> 812 explicit constexpr 813 optional(in_place_t, _Args&&... __args) 814 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 815 : _Base(std::in_place, std::forward<_Args>(__args)...) { } 816 817 template<typename _Up, typename... _Args, 818 _Requires<is_constructible<_Tp, 819 initializer_list<_Up>&, 820 _Args...>> = false> 821 explicit constexpr 822 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 823 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, 824 _Args...>) 825 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } 826 827 828 // Assignment operators. 829 _GLIBCXX20_CONSTEXPR optional& 830 operator=(nullopt_t) noexcept 831 { 832 this->_M_reset(); 833 return *this; 834 } 835 836 template<typename _Up = _Tp> 837 _GLIBCXX20_CONSTEXPR 838 enable_if_t<__and_v<__not_self<_Up>, 839 __not_<__and_<is_scalar<_Tp>, 840 is_same<_Tp, decay_t<_Up>>>>, 841 is_constructible<_Tp, _Up>, 842 is_assignable<_Tp&, _Up>>, 843 optional&> 844 operator=(_Up&& __u) 845 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, 846 is_nothrow_assignable<_Tp&, _Up>>) 847 { 848 if (this->_M_is_engaged()) 849 this->_M_get() = std::forward<_Up>(__u); 850 else 851 this->_M_construct(std::forward<_Up>(__u)); 852 853 return *this; 854 } 855 856 template<typename _Up> 857 _GLIBCXX20_CONSTEXPR 858 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, 859 is_constructible<_Tp, const _Up&>, 860 is_assignable<_Tp&, const _Up&>, 861 __not_<__converts_from_optional<_Tp, _Up>>, 862 __not_<__assigns_from_optional<_Tp, _Up>>>, 863 optional&> 864 operator=(const optional<_Up>& __u) 865 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>, 866 is_nothrow_assignable<_Tp&, const _Up&>>) 867 { 868 if (__u) 869 { 870 if (this->_M_is_engaged()) 871 this->_M_get() = *__u; 872 else 873 this->_M_construct(*__u); 874 } 875 else 876 { 877 this->_M_reset(); 878 } 879 return *this; 880 } 881 882 template<typename _Up> 883 _GLIBCXX20_CONSTEXPR 884 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, 885 is_constructible<_Tp, _Up>, 886 is_assignable<_Tp&, _Up>, 887 __not_<__converts_from_optional<_Tp, _Up>>, 888 __not_<__assigns_from_optional<_Tp, _Up>>>, 889 optional&> 890 operator=(optional<_Up>&& __u) 891 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, 892 is_nothrow_assignable<_Tp&, _Up>>) 893 { 894 if (__u) 895 { 896 if (this->_M_is_engaged()) 897 this->_M_get() = std::move(*__u); 898 else 899 this->_M_construct(std::move(*__u)); 900 } 901 else 902 { 903 this->_M_reset(); 904 } 905 906 return *this; 907 } 908 909 template<typename... _Args> 910 _GLIBCXX20_CONSTEXPR 911 enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&> 912 emplace(_Args&&... __args) 913 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 914 { 915 this->_M_reset(); 916 this->_M_construct(std::forward<_Args>(__args)...); 917 return this->_M_get(); 918 } 919 920 template<typename _Up, typename... _Args> 921 _GLIBCXX20_CONSTEXPR 922 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 923 _Tp&> 924 emplace(initializer_list<_Up> __il, _Args&&... __args) 925 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, 926 _Args...>) 927 { 928 this->_M_reset(); 929 this->_M_construct(__il, std::forward<_Args>(__args)...); 930 return this->_M_get(); 931 } 932 933 // Destructor is implicit, implemented in _Optional_base. 934 935 // Swap. 936 _GLIBCXX20_CONSTEXPR void 937 swap(optional& __other) 938 noexcept(is_nothrow_move_constructible_v<_Tp> 939 && is_nothrow_swappable_v<_Tp>) 940 { 941 using std::swap; 942 943 if (this->_M_is_engaged() && __other._M_is_engaged()) 944 swap(this->_M_get(), __other._M_get()); 945 else if (this->_M_is_engaged()) 946 { 947 __other._M_construct(std::move(this->_M_get())); 948 this->_M_destruct(); 949 } 950 else if (__other._M_is_engaged()) 951 { 952 this->_M_construct(std::move(__other._M_get())); 953 __other._M_destruct(); 954 } 955 } 956 957 // Observers. 958 constexpr const _Tp* 959 operator->() const noexcept 960 { return std::__addressof(this->_M_get()); } 961 962 constexpr _Tp* 963 operator->() noexcept 964 { return std::__addressof(this->_M_get()); } 965 966 constexpr const _Tp& 967 operator*() const& noexcept 968 { return this->_M_get(); } 969 970 constexpr _Tp& 971 operator*()& noexcept 972 { return this->_M_get(); } 973 974 constexpr _Tp&& 975 operator*()&& noexcept 976 { return std::move(this->_M_get()); } 977 978 constexpr const _Tp&& 979 operator*() const&& noexcept 980 { return std::move(this->_M_get()); } 981 982 constexpr explicit operator bool() const noexcept 983 { return this->_M_is_engaged(); } 984 985 constexpr bool has_value() const noexcept 986 { return this->_M_is_engaged(); } 987 988 constexpr const _Tp& 989 value() const& 990 { 991 if (this->_M_is_engaged()) 992 return this->_M_get(); 993 __throw_bad_optional_access(); 994 } 995 996 constexpr _Tp& 997 value()& 998 { 999 if (this->_M_is_engaged()) 1000 return this->_M_get(); 1001 __throw_bad_optional_access(); 1002 } 1003 1004 constexpr _Tp&& 1005 value()&& 1006 { 1007 if (this->_M_is_engaged()) 1008 return std::move(this->_M_get()); 1009 __throw_bad_optional_access(); 1010 } 1011 1012 constexpr const _Tp&& 1013 value() const&& 1014 { 1015 if (this->_M_is_engaged()) 1016 return std::move(this->_M_get()); 1017 __throw_bad_optional_access(); 1018 } 1019 1020 template<typename _Up> 1021 constexpr _Tp 1022 value_or(_Up&& __u) const& 1023 { 1024 static_assert(is_copy_constructible_v<_Tp>); 1025 static_assert(is_convertible_v<_Up&&, _Tp>); 1026 1027 if (this->_M_is_engaged()) 1028 return this->_M_get(); 1029 else 1030 return static_cast<_Tp>(std::forward<_Up>(__u)); 1031 } 1032 1033 template<typename _Up> 1034 constexpr _Tp 1035 value_or(_Up&& __u) && 1036 { 1037 static_assert(is_move_constructible_v<_Tp>); 1038 static_assert(is_convertible_v<_Up&&, _Tp>); 1039 1040 if (this->_M_is_engaged()) 1041 return std::move(this->_M_get()); 1042 else 1043 return static_cast<_Tp>(std::forward<_Up>(__u)); 1044 } 1045 1046 #if __cpp_lib_optional >= 202110L 1047 // [optional.monadic] 1048 1049 template<typename _Fn> 1050 constexpr auto 1051 and_then(_Fn&& __f) & 1052 { 1053 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp&>>; 1054 static_assert(__is_optional_v<remove_cvref_t<_Up>>, 1055 "the function passed to std::optional<T>::and_then " 1056 "must return a std::optional"); 1057 if (has_value()) 1058 return std::__invoke(std::forward<_Fn>(__f), **this); 1059 else 1060 return _Up(); 1061 } 1062 1063 template<typename _Fn> 1064 constexpr auto 1065 and_then(_Fn&& __f) const & 1066 { 1067 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp&>>; 1068 static_assert(__is_optional_v<_Up>, 1069 "the function passed to std::optional<T>::and_then " 1070 "must return a std::optional"); 1071 if (has_value()) 1072 return std::__invoke(std::forward<_Fn>(__f), **this); 1073 else 1074 return _Up(); 1075 } 1076 1077 template<typename _Fn> 1078 constexpr auto 1079 and_then(_Fn&& __f) && 1080 { 1081 using _Up = remove_cvref_t<invoke_result_t<_Fn, _Tp>>; 1082 static_assert(__is_optional_v<remove_cvref_t<_Up>>, 1083 "the function passed to std::optional<T>::and_then " 1084 "must return a std::optional"); 1085 if (has_value()) 1086 return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); 1087 else 1088 return _Up(); 1089 } 1090 1091 template<typename _Fn> 1092 constexpr auto 1093 and_then(_Fn&& __f) const && 1094 { 1095 using _Up = remove_cvref_t<invoke_result_t<_Fn, const _Tp>>; 1096 static_assert(__is_optional_v<remove_cvref_t<_Up>>, 1097 "the function passed to std::optional<T>::and_then " 1098 "must return a std::optional"); 1099 if (has_value()) 1100 return std::__invoke(std::forward<_Fn>(__f), std::move(**this)); 1101 else 1102 return _Up(); 1103 } 1104 1105 template<typename _Fn> 1106 constexpr auto 1107 transform(_Fn&& __f) & 1108 { 1109 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp&>>; 1110 if (has_value()) 1111 return optional<_Up>(_Optional_func<_Fn>{__f}, **this); 1112 else 1113 return optional<_Up>(); 1114 } 1115 1116 template<typename _Fn> 1117 constexpr auto 1118 transform(_Fn&& __f) const & 1119 { 1120 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp&>>; 1121 if (has_value()) 1122 return optional<_Up>(_Optional_func<_Fn>{__f}, **this); 1123 else 1124 return optional<_Up>(); 1125 } 1126 1127 template<typename _Fn> 1128 constexpr auto 1129 transform(_Fn&& __f) && 1130 { 1131 using _Up = remove_cv_t<invoke_result_t<_Fn, _Tp>>; 1132 if (has_value()) 1133 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); 1134 else 1135 return optional<_Up>(); 1136 } 1137 1138 template<typename _Fn> 1139 constexpr auto 1140 transform(_Fn&& __f) const && 1141 { 1142 using _Up = remove_cv_t<invoke_result_t<_Fn, const _Tp>>; 1143 if (has_value()) 1144 return optional<_Up>(_Optional_func<_Fn>{__f}, std::move(**this)); 1145 else 1146 return optional<_Up>(); 1147 } 1148 1149 template<typename _Fn> requires invocable<_Fn> && copy_constructible<_Tp> 1150 constexpr optional 1151 or_else(_Fn&& __f) const& 1152 { 1153 using _Up = invoke_result_t<_Fn>; 1154 static_assert(is_same_v<remove_cvref_t<_Up>, optional>, 1155 "the function passed to std::optional<T>::or_else " 1156 "must return a std::optional<T>"); 1157 1158 if (has_value()) 1159 return *this; 1160 else 1161 return std::forward<_Fn>(__f)(); 1162 } 1163 1164 template<typename _Fn> requires invocable<_Fn> && move_constructible<_Tp> 1165 constexpr optional 1166 or_else(_Fn&& __f) && 1167 { 1168 using _Up = invoke_result_t<_Fn>; 1169 static_assert(is_same_v<remove_cvref_t<_Up>, optional>, 1170 "the function passed to std::optional<T>::or_else " 1171 "must return a std::optional<T>"); 1172 1173 if (has_value()) 1174 return std::move(*this); 1175 else 1176 return std::forward<_Fn>(__f)(); 1177 } 1178 #endif 1179 1180 _GLIBCXX20_CONSTEXPR void reset() noexcept { this->_M_reset(); } 1181 1182 private: 1183 #if __cplusplus >= 202002L 1184 template<typename _Up> friend class optional; 1185 1186 template<typename _Fn, typename _Value> 1187 explicit constexpr 1188 optional(_Optional_func<_Fn> __f, _Value&& __v) 1189 { 1190 this->_M_payload._M_apply(__f, std::forward<_Value>(__v)); 1191 } 1192 #endif 1193 }; 1194 1195 template<typename _Tp> 1196 using __optional_relop_t = 1197 enable_if_t<is_convertible<_Tp, bool>::value, bool>; 1198 1199 template<typename _Tp, typename _Up> 1200 using __optional_eq_t = __optional_relop_t< 1201 decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()) 1202 >; 1203 1204 template<typename _Tp, typename _Up> 1205 using __optional_ne_t = __optional_relop_t< 1206 decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()) 1207 >; 1208 1209 template<typename _Tp, typename _Up> 1210 using __optional_lt_t = __optional_relop_t< 1211 decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()) 1212 >; 1213 1214 template<typename _Tp, typename _Up> 1215 using __optional_gt_t = __optional_relop_t< 1216 decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()) 1217 >; 1218 1219 template<typename _Tp, typename _Up> 1220 using __optional_le_t = __optional_relop_t< 1221 decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()) 1222 >; 1223 1224 template<typename _Tp, typename _Up> 1225 using __optional_ge_t = __optional_relop_t< 1226 decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()) 1227 >; 1228 1229 // Comparisons between optional values. 1230 template<typename _Tp, typename _Up> 1231 constexpr auto 1232 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1233 -> __optional_eq_t<_Tp, _Up> 1234 { 1235 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 1236 && (!__lhs || *__lhs == *__rhs); 1237 } 1238 1239 template<typename _Tp, typename _Up> 1240 constexpr auto 1241 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1242 -> __optional_ne_t<_Tp, _Up> 1243 { 1244 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs) 1245 || (static_cast<bool>(__lhs) && *__lhs != *__rhs); 1246 } 1247 1248 template<typename _Tp, typename _Up> 1249 constexpr auto 1250 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1251 -> __optional_lt_t<_Tp, _Up> 1252 { 1253 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 1254 } 1255 1256 template<typename _Tp, typename _Up> 1257 constexpr auto 1258 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1259 -> __optional_gt_t<_Tp, _Up> 1260 { 1261 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs); 1262 } 1263 1264 template<typename _Tp, typename _Up> 1265 constexpr auto 1266 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1267 -> __optional_le_t<_Tp, _Up> 1268 { 1269 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs); 1270 } 1271 1272 template<typename _Tp, typename _Up> 1273 constexpr auto 1274 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1275 -> __optional_ge_t<_Tp, _Up> 1276 { 1277 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); 1278 } 1279 1280 #ifdef __cpp_lib_three_way_comparison 1281 template<typename _Tp, three_way_comparable_with<_Tp> _Up> 1282 constexpr compare_three_way_result_t<_Tp, _Up> 1283 operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) 1284 { 1285 return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); 1286 } 1287 #endif 1288 1289 // Comparisons with nullopt. 1290 template<typename _Tp> 1291 constexpr bool 1292 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 1293 { return !__lhs; } 1294 1295 #ifdef __cpp_lib_three_way_comparison 1296 template<typename _Tp> 1297 constexpr strong_ordering 1298 operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept 1299 { return bool(__x) <=> false; } 1300 #else 1301 template<typename _Tp> 1302 constexpr bool 1303 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 1304 { return !__rhs; } 1305 1306 template<typename _Tp> 1307 constexpr bool 1308 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 1309 { return static_cast<bool>(__lhs); } 1310 1311 template<typename _Tp> 1312 constexpr bool 1313 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 1314 { return static_cast<bool>(__rhs); } 1315 1316 template<typename _Tp> 1317 constexpr bool 1318 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 1319 { return false; } 1320 1321 template<typename _Tp> 1322 constexpr bool 1323 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 1324 { return static_cast<bool>(__rhs); } 1325 1326 template<typename _Tp> 1327 constexpr bool 1328 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 1329 { return static_cast<bool>(__lhs); } 1330 1331 template<typename _Tp> 1332 constexpr bool 1333 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 1334 { return false; } 1335 1336 template<typename _Tp> 1337 constexpr bool 1338 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 1339 { return !__lhs; } 1340 1341 template<typename _Tp> 1342 constexpr bool 1343 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 1344 { return true; } 1345 1346 template<typename _Tp> 1347 constexpr bool 1348 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 1349 { return true; } 1350 1351 template<typename _Tp> 1352 constexpr bool 1353 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 1354 { return !__rhs; } 1355 #endif // three-way-comparison 1356 1357 // Comparisons with value type. 1358 template<typename _Tp, typename _Up> 1359 constexpr auto 1360 operator==(const optional<_Tp>& __lhs, const _Up& __rhs) 1361 -> __optional_eq_t<_Tp, _Up> 1362 { return __lhs && *__lhs == __rhs; } 1363 1364 template<typename _Tp, typename _Up> 1365 constexpr auto 1366 operator==(const _Up& __lhs, const optional<_Tp>& __rhs) 1367 -> __optional_eq_t<_Up, _Tp> 1368 { return __rhs && __lhs == *__rhs; } 1369 1370 template<typename _Tp, typename _Up> 1371 constexpr auto 1372 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) 1373 -> __optional_ne_t<_Tp, _Up> 1374 { return !__lhs || *__lhs != __rhs; } 1375 1376 template<typename _Tp, typename _Up> 1377 constexpr auto 1378 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) 1379 -> __optional_ne_t<_Up, _Tp> 1380 { return !__rhs || __lhs != *__rhs; } 1381 1382 template<typename _Tp, typename _Up> 1383 constexpr auto 1384 operator<(const optional<_Tp>& __lhs, const _Up& __rhs) 1385 -> __optional_lt_t<_Tp, _Up> 1386 { return !__lhs || *__lhs < __rhs; } 1387 1388 template<typename _Tp, typename _Up> 1389 constexpr auto 1390 operator<(const _Up& __lhs, const optional<_Tp>& __rhs) 1391 -> __optional_lt_t<_Up, _Tp> 1392 { return __rhs && __lhs < *__rhs; } 1393 1394 template<typename _Tp, typename _Up> 1395 constexpr auto 1396 operator>(const optional<_Tp>& __lhs, const _Up& __rhs) 1397 -> __optional_gt_t<_Tp, _Up> 1398 { return __lhs && *__lhs > __rhs; } 1399 1400 template<typename _Tp, typename _Up> 1401 constexpr auto 1402 operator>(const _Up& __lhs, const optional<_Tp>& __rhs) 1403 -> __optional_gt_t<_Up, _Tp> 1404 { return !__rhs || __lhs > *__rhs; } 1405 1406 template<typename _Tp, typename _Up> 1407 constexpr auto 1408 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) 1409 -> __optional_le_t<_Tp, _Up> 1410 { return !__lhs || *__lhs <= __rhs; } 1411 1412 template<typename _Tp, typename _Up> 1413 constexpr auto 1414 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) 1415 -> __optional_le_t<_Up, _Tp> 1416 { return __rhs && __lhs <= *__rhs; } 1417 1418 template<typename _Tp, typename _Up> 1419 constexpr auto 1420 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) 1421 -> __optional_ge_t<_Tp, _Up> 1422 { return __lhs && *__lhs >= __rhs; } 1423 1424 template<typename _Tp, typename _Up> 1425 constexpr auto 1426 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) 1427 -> __optional_ge_t<_Up, _Tp> 1428 { return !__rhs || __lhs >= *__rhs; } 1429 1430 #ifdef __cpp_lib_three_way_comparison 1431 template<typename _Tp, typename _Up> 1432 requires (!__is_optional_v<_Up>) 1433 && requires { typename compare_three_way_result_t<_Tp, _Up>; } 1434 && three_way_comparable_with<_Tp, _Up> 1435 constexpr compare_three_way_result_t<_Tp, _Up> 1436 operator<=>(const optional<_Tp>& __x, const _Up& __v) 1437 { return bool(__x) ? *__x <=> __v : strong_ordering::less; } 1438 #endif 1439 1440 // Swap and creation functions. 1441 1442 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1443 // 2748. swappable traits for optionals 1444 template<typename _Tp> 1445 _GLIBCXX20_CONSTEXPR 1446 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>> 1447 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 1448 noexcept(noexcept(__lhs.swap(__rhs))) 1449 { __lhs.swap(__rhs); } 1450 1451 template<typename _Tp> 1452 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)> 1453 swap(optional<_Tp>&, optional<_Tp>&) = delete; 1454 1455 template<typename _Tp> 1456 constexpr 1457 enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>, 1458 optional<decay_t<_Tp>>> 1459 make_optional(_Tp&& __t) 1460 noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>) 1461 { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; } 1462 1463 template<typename _Tp, typename... _Args> 1464 constexpr 1465 enable_if_t<is_constructible_v<_Tp, _Args...>, 1466 optional<_Tp>> 1467 make_optional(_Args&&... __args) 1468 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 1469 { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; } 1470 1471 template<typename _Tp, typename _Up, typename... _Args> 1472 constexpr 1473 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1474 optional<_Tp>> 1475 make_optional(initializer_list<_Up> __il, _Args&&... __args) 1476 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) 1477 { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; } 1478 1479 // Hash. 1480 1481 template<typename _Tp, typename _Up = remove_const_t<_Tp>, 1482 bool = __poison_hash<_Up>::__enable_hash_call> 1483 struct __optional_hash_call_base 1484 { 1485 size_t 1486 operator()(const optional<_Tp>& __t) const 1487 noexcept(noexcept(hash<_Up>{}(*__t))) 1488 { 1489 // We pick an arbitrary hash for disengaged optionals which hopefully 1490 // usual values of _Tp won't typically hash to. 1491 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 1492 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; 1493 } 1494 }; 1495 1496 template<typename _Tp, typename _Up> 1497 struct __optional_hash_call_base<_Tp, _Up, false> {}; 1498 1499 template<typename _Tp> 1500 struct hash<optional<_Tp>> 1501 : private __poison_hash<remove_const_t<_Tp>>, 1502 public __optional_hash_call_base<_Tp> 1503 { 1504 using result_type [[__deprecated__]] = size_t; 1505 using argument_type [[__deprecated__]] = optional<_Tp>; 1506 }; 1507 1508 template<typename _Tp> 1509 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>> 1510 { }; 1511 1512 /// @} 1513 1514 #if __cpp_deduction_guides >= 201606 1515 template <typename _Tp> optional(_Tp) -> optional<_Tp>; 1516 #endif 1517 1518 _GLIBCXX_END_NAMESPACE_VERSION 1519 } // namespace std 1520 1521 #endif // __cpp_lib_optional 1522 1523 #endif // _GLIBCXX_OPTIONAL 1524