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