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