1// <optional> -*- C++ -*- 2 3// Copyright (C) 2013-2017 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 constexpr optionals. 102 template <typename _Tp, 103 bool /*_TrivialCopyMove*/ = 104 is_trivially_copy_constructible<_Tp>::value 105 && is_trivially_move_constructible<_Tp>::value, 106 bool /*_ShouldProvideDestructor*/ = 107 is_trivially_destructible<_Tp>::value> 108 struct _Optional_payload 109 { 110 constexpr _Optional_payload() 111 : _M_empty() {} 112 113 template<typename... _Args> 114 constexpr _Optional_payload(in_place_t, _Args&&... __args) 115 : _M_payload(std::forward<_Args>(__args)...), 116 _M_engaged(true) 117 {} 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 125 template <class _Up> struct __ctor_tag {}; 126 127 constexpr _Optional_payload(__ctor_tag<bool>, 128 const _Tp& __other) 129 : _M_payload(__other), 130 _M_engaged(true) 131 {} 132 133 constexpr _Optional_payload(__ctor_tag<void>) 134 : _M_empty() 135 {} 136 137 constexpr _Optional_payload(__ctor_tag<bool>, _Tp&& __other) 138 : _M_payload(std::move(__other)), 139 _M_engaged(true) 140 {} 141 142 constexpr _Optional_payload(bool __engaged, 143 const _Optional_payload& __other) 144 : _Optional_payload(__engaged ? 145 _Optional_payload(__ctor_tag<bool>{}, 146 __other._M_payload) : 147 _Optional_payload(__ctor_tag<void>{})) 148 {} 149 150 constexpr _Optional_payload(bool __engaged, 151 _Optional_payload&& __other) 152 : _Optional_payload(__engaged 153 ? _Optional_payload(__ctor_tag<bool>{}, 154 std::move(__other._M_payload)) 155 : _Optional_payload(__ctor_tag<void>{})) 156 {} 157 158 using _Stored_type = remove_const_t<_Tp>; 159 struct _Empty_byte { }; 160 union { 161 _Empty_byte _M_empty; 162 _Stored_type _M_payload; 163 }; 164 bool _M_engaged = false; 165 }; 166 167 // Payload for non-constexpr optionals with non-trivial destructor. 168 template <typename _Tp> 169 struct _Optional_payload<_Tp, false, false> 170 { 171 constexpr _Optional_payload() 172 : _M_empty() {} 173 174 template <typename... _Args> 175 constexpr _Optional_payload(in_place_t, _Args&&... __args) 176 : _M_payload(std::forward<_Args>(__args)...), 177 _M_engaged(true) {} 178 179 template<typename _Up, typename... _Args> 180 constexpr _Optional_payload(std::initializer_list<_Up> __il, 181 _Args&&... __args) 182 : _M_payload(__il, std::forward<_Args>(__args)...), 183 _M_engaged(true) {} 184 constexpr 185 _Optional_payload(bool __engaged, const _Optional_payload& __other) 186 : _Optional_payload(__other) 187 {} 188 189 constexpr 190 _Optional_payload(bool __engaged, _Optional_payload&& __other) 191 : _Optional_payload(std::move(__other)) 192 {} 193 194 constexpr _Optional_payload(const _Optional_payload& __other) 195 { 196 if (__other._M_engaged) 197 this->_M_construct(__other._M_payload); 198 } 199 200 constexpr _Optional_payload(_Optional_payload&& __other) 201 { 202 if (__other._M_engaged) 203 this->_M_construct(std::move(__other._M_payload)); 204 } 205 206 using _Stored_type = remove_const_t<_Tp>; 207 struct _Empty_byte { }; 208 union { 209 _Empty_byte _M_empty; 210 _Stored_type _M_payload; 211 }; 212 bool _M_engaged = false; 213 214 ~_Optional_payload() 215 { 216 if (_M_engaged) 217 _M_payload.~_Stored_type(); 218 } 219 220 template<typename... _Args> 221 void 222 _M_construct(_Args&&... __args) 223 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 224 { 225 ::new ((void *) std::__addressof(this->_M_payload)) 226 _Stored_type(std::forward<_Args>(__args)...); 227 this->_M_engaged = true; 228 } 229 }; 230 231 // Payload for non-constexpr optionals with trivial destructor. 232 template <typename _Tp> 233 struct _Optional_payload<_Tp, false, true> 234 { 235 constexpr _Optional_payload() 236 : _M_empty() {} 237 238 template <typename... _Args> 239 constexpr _Optional_payload(in_place_t, _Args&&... __args) 240 : _M_payload(std::forward<_Args>(__args)...), 241 _M_engaged(true) {} 242 243 template<typename _Up, typename... _Args> 244 constexpr _Optional_payload(std::initializer_list<_Up> __il, 245 _Args&&... __args) 246 : _M_payload(__il, std::forward<_Args>(__args)...), 247 _M_engaged(true) {} 248 constexpr 249 _Optional_payload(bool __engaged, const _Optional_payload& __other) 250 : _Optional_payload(__other) 251 {} 252 253 constexpr 254 _Optional_payload(bool __engaged, _Optional_payload&& __other) 255 : _Optional_payload(std::move(__other)) 256 {} 257 258 constexpr _Optional_payload(const _Optional_payload& __other) 259 { 260 if (__other._M_engaged) 261 this->_M_construct(__other._M_payload); 262 } 263 264 constexpr _Optional_payload(_Optional_payload&& __other) 265 { 266 if (__other._M_engaged) 267 this->_M_construct(std::move(__other._M_payload)); 268 } 269 270 using _Stored_type = remove_const_t<_Tp>; 271 struct _Empty_byte { }; 272 union { 273 _Empty_byte _M_empty; 274 _Stored_type _M_payload; 275 }; 276 bool _M_engaged = false; 277 278 template<typename... _Args> 279 void 280 _M_construct(_Args&&... __args) 281 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 282 { 283 ::new ((void *) std::__addressof(this->_M_payload)) 284 _Stored_type(std::forward<_Args>(__args)...); 285 this->_M_engaged = true; 286 } 287 }; 288 289 /** 290 * @brief Class template that holds the necessary state for @ref optional 291 * and that has the responsibility for construction and the special members. 292 * 293 * Such a separate base class template is necessary in order to 294 * conditionally enable the special members (e.g. copy/move constructors). 295 * Note that this means that @ref _Optional_base implements the 296 * functionality for copy and move assignment, but not for converting 297 * assignment. 298 * 299 * @see optional, _Enable_special_members 300 */ 301 template<typename _Tp> 302 class _Optional_base 303 { 304 private: 305 // Remove const to avoid prohibition of reusing object storage for 306 // const-qualified types in [3.8/9]. This is strictly internal 307 // and even optional itself is oblivious to it. 308 using _Stored_type = remove_const_t<_Tp>; 309 310 public: 311 312 // Constructors for disengaged optionals. 313 constexpr _Optional_base() noexcept 314 { } 315 316 constexpr _Optional_base(nullopt_t) noexcept 317 { } 318 319 // Constructors for engaged optionals. 320 template<typename... _Args, 321 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 322 constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 323 : _M_payload(in_place, 324 std::forward<_Args>(__args)...) { } 325 326 template<typename _Up, typename... _Args, 327 enable_if_t<is_constructible_v<_Tp, 328 initializer_list<_Up>&, 329 _Args&&...>, bool> = false> 330 constexpr explicit _Optional_base(in_place_t, 331 initializer_list<_Up> __il, 332 _Args&&... __args) 333 : _M_payload(in_place, 334 __il, std::forward<_Args>(__args)...) 335 { } 336 337 // Copy and move constructors. 338 constexpr _Optional_base(const _Optional_base& __other) 339 : _M_payload(__other._M_payload._M_engaged, 340 __other._M_payload) 341 { } 342 343 constexpr _Optional_base(_Optional_base&& __other) 344 noexcept(is_nothrow_move_constructible<_Tp>()) 345 : _M_payload(__other._M_payload._M_engaged, 346 std::move(__other._M_payload)) 347 { } 348 349 // Assignment operators. 350 _Optional_base& 351 operator=(const _Optional_base& __other) 352 { 353 if (this->_M_payload._M_engaged && __other._M_payload._M_engaged) 354 this->_M_get() = __other._M_get(); 355 else 356 { 357 if (__other._M_payload._M_engaged) 358 this->_M_construct(__other._M_get()); 359 else 360 this->_M_reset(); 361 } 362 363 return *this; 364 } 365 366 _Optional_base& 367 operator=(_Optional_base&& __other) 368 noexcept(__and_<is_nothrow_move_constructible<_Tp>, 369 is_nothrow_move_assignable<_Tp>>()) 370 { 371 if (this->_M_payload._M_engaged && __other._M_payload._M_engaged) 372 this->_M_get() = std::move(__other._M_get()); 373 else 374 { 375 if (__other._M_payload._M_engaged) 376 this->_M_construct(std::move(__other._M_get())); 377 else 378 this->_M_reset(); 379 } 380 return *this; 381 } 382 // The following functionality is also needed by optional, hence the 383 // protected accessibility. 384 protected: 385 constexpr bool _M_is_engaged() const noexcept 386 { return this->_M_payload._M_engaged; } 387 388 // The _M_get operations have _M_engaged as a precondition. 389 constexpr _Tp& 390 _M_get() noexcept 391 { return this->_M_payload._M_payload; } 392 393 constexpr const _Tp& 394 _M_get() const noexcept 395 { return this->_M_payload._M_payload; } 396 397 // The _M_construct operation has !_M_engaged as a precondition 398 // while _M_destruct has _M_engaged as a precondition. 399 template<typename... _Args> 400 void 401 _M_construct(_Args&&... __args) 402 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 403 { 404 ::new (std::__addressof(this->_M_payload._M_payload)) 405 _Stored_type(std::forward<_Args>(__args)...); 406 this->_M_payload._M_engaged = true; 407 } 408 409 void 410 _M_destruct() 411 { 412 this->_M_payload._M_engaged = false; 413 this->_M_payload._M_payload.~_Stored_type(); 414 } 415 416 // _M_reset is a 'safe' operation with no precondition. 417 void 418 _M_reset() 419 { 420 if (this->_M_payload._M_engaged) 421 this->_M_destruct(); 422 } 423 424 private: 425 _Optional_payload<_Tp> _M_payload; 426 }; 427 428 template<typename _Tp> 429 class optional; 430 431 template<typename _Tp, typename _Up> 432 using __converts_from_optional = 433 __or_<is_constructible<_Tp, const optional<_Up>&>, 434 is_constructible<_Tp, optional<_Up>&>, 435 is_constructible<_Tp, const optional<_Up>&&>, 436 is_constructible<_Tp, optional<_Up>&&>, 437 is_convertible<const optional<_Up>&, _Tp>, 438 is_convertible<optional<_Up>&, _Tp>, 439 is_convertible<const optional<_Up>&&, _Tp>, 440 is_convertible<optional<_Up>&&, _Tp>>; 441 442 template<typename _Tp, typename _Up> 443 using __assigns_from_optional = 444 __or_<is_assignable<_Tp&, const optional<_Up>&>, 445 is_assignable<_Tp&, optional<_Up>&>, 446 is_assignable<_Tp&, const optional<_Up>&&>, 447 is_assignable<_Tp&, optional<_Up>&&>>; 448 449 /** 450 * @brief Class template for optional values. 451 */ 452 template<typename _Tp> 453 class optional 454 : private _Optional_base<_Tp>, 455 private _Enable_copy_move< 456 // Copy constructor. 457 is_copy_constructible<_Tp>::value, 458 // Copy assignment. 459 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 460 // Move constructor. 461 is_move_constructible<_Tp>::value, 462 // Move assignment. 463 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 464 // Unique tag type. 465 optional<_Tp>> 466 { 467 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 468 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 469 __not_<is_reference<_Tp>>>(), 470 "Invalid instantiation of optional<T>"); 471 472 private: 473 using _Base = _Optional_base<_Tp>; 474 475 public: 476 using value_type = _Tp; 477 478 constexpr optional() = default; 479 480 constexpr optional(nullopt_t) noexcept 481 : _Base(nullopt) { } 482 483 // Converting constructors for engaged optionals. 484 template <typename _Up = _Tp, 485 enable_if_t<__and_< 486 __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 487 __not_<is_same<in_place_t, decay_t<_Up>>>, 488 is_constructible<_Tp, _Up&&>, 489 is_convertible<_Up&&, _Tp> 490 >::value, bool> = true> 491 constexpr optional(_Up&& __t) 492 : _Base(std::in_place, std::forward<_Up>(__t)) { } 493 494 template <typename _Up = _Tp, 495 enable_if_t<__and_< 496 __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 497 __not_<is_same<in_place_t, decay_t<_Up>>>, 498 is_constructible<_Tp, _Up&&>, 499 __not_<is_convertible<_Up&&, _Tp>> 500 >::value, bool> = false> 501 explicit constexpr optional(_Up&& __t) 502 : _Base(std::in_place, std::forward<_Up>(__t)) { } 503 504 template <typename _Up, 505 enable_if_t<__and_< 506 __not_<is_same<_Tp, _Up>>, 507 is_constructible<_Tp, const _Up&>, 508 is_convertible<const _Up&, _Tp>, 509 __not_<__converts_from_optional<_Tp, _Up>> 510 >::value, bool> = true> 511 constexpr optional(const optional<_Up>& __t) 512 { 513 if (__t) 514 emplace(*__t); 515 } 516 517 template <typename _Up, 518 enable_if_t<__and_< 519 __not_<is_same<_Tp, _Up>>, 520 is_constructible<_Tp, const _Up&>, 521 __not_<is_convertible<const _Up&, _Tp>>, 522 __not_<__converts_from_optional<_Tp, _Up>> 523 >::value, bool> = false> 524 explicit constexpr optional(const optional<_Up>& __t) 525 { 526 if (__t) 527 emplace(*__t); 528 } 529 530 template <typename _Up, 531 enable_if_t<__and_< 532 __not_<is_same<_Tp, _Up>>, 533 is_constructible<_Tp, _Up&&>, 534 is_convertible<_Up&&, _Tp>, 535 __not_<__converts_from_optional<_Tp, _Up>> 536 >::value, bool> = true> 537 constexpr optional(optional<_Up>&& __t) 538 { 539 if (__t) 540 emplace(std::move(*__t)); 541 } 542 543 template <typename _Up, 544 enable_if_t<__and_< 545 __not_<is_same<_Tp, _Up>>, 546 is_constructible<_Tp, _Up&&>, 547 __not_<is_convertible<_Up&&, _Tp>>, 548 __not_<__converts_from_optional<_Tp, _Up>> 549 >::value, bool> = false> 550 explicit constexpr optional(optional<_Up>&& __t) 551 { 552 if (__t) 553 emplace(std::move(*__t)); 554 } 555 556 template<typename... _Args, 557 enable_if_t<is_constructible_v<_Tp, _Args&&...>, bool> = false> 558 explicit constexpr optional(in_place_t, _Args&&... __args) 559 : _Base(std::in_place, std::forward<_Args>(__args)...) { } 560 561 template<typename _Up, typename... _Args, 562 enable_if_t<is_constructible_v<_Tp, 563 initializer_list<_Up>&, 564 _Args&&...>, bool> = false> 565 explicit constexpr optional(in_place_t, 566 initializer_list<_Up> __il, 567 _Args&&... __args) 568 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } 569 570 // Assignment operators. 571 optional& 572 operator=(nullopt_t) noexcept 573 { 574 this->_M_reset(); 575 return *this; 576 } 577 578 template<typename _Up = _Tp> 579 enable_if_t<__and_< 580 __not_<is_same<optional<_Tp>, decay_t<_Up>>>, 581 is_constructible<_Tp, _Up>, 582 __not_<__and_<is_scalar<_Tp>, 583 is_same<_Tp, decay_t<_Up>>>>, 584 is_assignable<_Tp&, _Up>>::value, 585 optional&> 586 operator=(_Up&& __u) 587 { 588 if (this->_M_is_engaged()) 589 this->_M_get() = std::forward<_Up>(__u); 590 else 591 this->_M_construct(std::forward<_Up>(__u)); 592 593 return *this; 594 } 595 596 template<typename _Up> 597 enable_if_t<__and_< 598 __not_<is_same<_Tp, _Up>>, 599 is_constructible<_Tp, const _Up&>, 600 is_assignable<_Tp&, _Up>, 601 __not_<__converts_from_optional<_Tp, _Up>>, 602 __not_<__assigns_from_optional<_Tp, _Up>> 603 >::value, 604 optional&> 605 operator=(const optional<_Up>& __u) 606 { 607 if (__u) 608 { 609 if (this->_M_is_engaged()) 610 this->_M_get() = *__u; 611 else 612 this->_M_construct(*__u); 613 } 614 else 615 { 616 this->_M_reset(); 617 } 618 return *this; 619 } 620 621 template<typename _Up> 622 enable_if_t<__and_< 623 __not_<is_same<_Tp, _Up>>, 624 is_constructible<_Tp, _Up>, 625 is_assignable<_Tp&, _Up>, 626 __not_<__converts_from_optional<_Tp, _Up>>, 627 __not_<__assigns_from_optional<_Tp, _Up>> 628 >::value, 629 optional&> 630 operator=(optional<_Up>&& __u) 631 { 632 if (__u) 633 { 634 if (this->_M_is_engaged()) 635 this->_M_get() = std::move(*__u); 636 else 637 this->_M_construct(std::move(*__u)); 638 } 639 else 640 { 641 this->_M_reset(); 642 } 643 644 return *this; 645 } 646 647 template<typename... _Args> 648 enable_if_t<is_constructible<_Tp, _Args&&...>::value, _Tp&> 649 emplace(_Args&&... __args) 650 { 651 this->_M_reset(); 652 this->_M_construct(std::forward<_Args>(__args)...); 653 return this->_M_get(); 654 } 655 656 template<typename _Up, typename... _Args> 657 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 658 _Args&&...>::value, _Tp&> 659 emplace(initializer_list<_Up> __il, _Args&&... __args) 660 { 661 this->_M_reset(); 662 this->_M_construct(__il, std::forward<_Args>(__args)...); 663 return this->_M_get(); 664 } 665 666 // Destructor is implicit, implemented in _Optional_base. 667 668 // Swap. 669 void 670 swap(optional& __other) 671 noexcept(is_nothrow_move_constructible<_Tp>() 672 && is_nothrow_swappable_v<_Tp>) 673 { 674 using std::swap; 675 676 if (this->_M_is_engaged() && __other._M_is_engaged()) 677 swap(this->_M_get(), __other._M_get()); 678 else if (this->_M_is_engaged()) 679 { 680 __other._M_construct(std::move(this->_M_get())); 681 this->_M_destruct(); 682 } 683 else if (__other._M_is_engaged()) 684 { 685 this->_M_construct(std::move(__other._M_get())); 686 __other._M_destruct(); 687 } 688 } 689 690 // Observers. 691 constexpr const _Tp* 692 operator->() const 693 { return std::__addressof(this->_M_get()); } 694 695 _Tp* 696 operator->() 697 { return std::__addressof(this->_M_get()); } 698 699 constexpr const _Tp& 700 operator*() const& 701 { return this->_M_get(); } 702 703 constexpr _Tp& 704 operator*()& 705 { return this->_M_get(); } 706 707 constexpr _Tp&& 708 operator*()&& 709 { return std::move(this->_M_get()); } 710 711 constexpr const _Tp&& 712 operator*() const&& 713 { return std::move(this->_M_get()); } 714 715 constexpr explicit operator bool() const noexcept 716 { return this->_M_is_engaged(); } 717 718 constexpr bool has_value() const noexcept 719 { return this->_M_is_engaged(); } 720 721 constexpr const _Tp& 722 value() const& 723 { 724 return this->_M_is_engaged() 725 ? this->_M_get() 726 : (__throw_bad_optional_access(), 727 this->_M_get()); 728 } 729 730 constexpr _Tp& 731 value()& 732 { 733 return this->_M_is_engaged() 734 ? this->_M_get() 735 : (__throw_bad_optional_access(), 736 this->_M_get()); 737 } 738 739 constexpr _Tp&& 740 value()&& 741 { 742 return this->_M_is_engaged() 743 ? std::move(this->_M_get()) 744 : (__throw_bad_optional_access(), 745 std::move(this->_M_get())); 746 } 747 748 constexpr const _Tp&& 749 value() const&& 750 { 751 return this->_M_is_engaged() 752 ? std::move(this->_M_get()) 753 : (__throw_bad_optional_access(), 754 std::move(this->_M_get())); 755 } 756 757 template<typename _Up> 758 constexpr _Tp 759 value_or(_Up&& __u) const& 760 { 761 static_assert(__and_<is_copy_constructible<_Tp>, 762 is_convertible<_Up&&, _Tp>>(), 763 "Cannot return value"); 764 765 return this->_M_is_engaged() 766 ? this->_M_get() 767 : static_cast<_Tp>(std::forward<_Up>(__u)); 768 } 769 770 template<typename _Up> 771 _Tp 772 value_or(_Up&& __u) && 773 { 774 static_assert(__and_<is_move_constructible<_Tp>, 775 is_convertible<_Up&&, _Tp>>(), 776 "Cannot return value" ); 777 778 return this->_M_is_engaged() 779 ? std::move(this->_M_get()) 780 : static_cast<_Tp>(std::forward<_Up>(__u)); 781 } 782 void reset() noexcept { this->_M_reset(); } 783 }; 784 785 template<typename _Tp> 786 using __optional_relop_t = 787 enable_if_t<is_convertible<_Tp, bool>::value, bool>; 788 789 // Comparisons between optional values. 790 template<typename _Tp, typename _Up> 791 constexpr auto 792 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 793 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())> 794 { 795 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 796 && (!__lhs || *__lhs == *__rhs); 797 } 798 799 template<typename _Tp, typename _Up> 800 constexpr auto 801 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 802 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())> 803 { 804 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs) 805 || (static_cast<bool>(__lhs) && *__lhs != *__rhs); 806 } 807 808 template<typename _Tp, typename _Up> 809 constexpr auto 810 operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 811 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())> 812 { 813 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 814 } 815 816 template<typename _Tp, typename _Up> 817 constexpr auto 818 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 819 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())> 820 { 821 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs); 822 } 823 824 template<typename _Tp, typename _Up> 825 constexpr auto 826 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 827 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())> 828 { 829 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs); 830 } 831 832 template<typename _Tp, typename _Up> 833 constexpr auto 834 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 835 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())> 836 { 837 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); 838 } 839 840 // Comparisons with nullopt. 841 template<typename _Tp> 842 constexpr bool 843 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 844 { return !__lhs; } 845 846 template<typename _Tp> 847 constexpr bool 848 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 849 { return !__rhs; } 850 851 template<typename _Tp> 852 constexpr bool 853 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 854 { return static_cast<bool>(__lhs); } 855 856 template<typename _Tp> 857 constexpr bool 858 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 859 { return static_cast<bool>(__rhs); } 860 861 template<typename _Tp> 862 constexpr bool 863 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 864 { return false; } 865 866 template<typename _Tp> 867 constexpr bool 868 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 869 { return static_cast<bool>(__rhs); } 870 871 template<typename _Tp> 872 constexpr bool 873 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 874 { return static_cast<bool>(__lhs); } 875 876 template<typename _Tp> 877 constexpr bool 878 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 879 { return false; } 880 881 template<typename _Tp> 882 constexpr bool 883 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 884 { return !__lhs; } 885 886 template<typename _Tp> 887 constexpr bool 888 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 889 { return true; } 890 891 template<typename _Tp> 892 constexpr bool 893 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 894 { return true; } 895 896 template<typename _Tp> 897 constexpr bool 898 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 899 { return !__rhs; } 900 901 // Comparisons with value type. 902 template<typename _Tp, typename _Up> 903 constexpr auto 904 operator==(const optional<_Tp>& __lhs, const _Up& __rhs) 905 -> __optional_relop_t<decltype(declval<_Tp>() == declval<_Up>())> 906 { return __lhs && *__lhs == __rhs; } 907 908 template<typename _Tp, typename _Up> 909 constexpr auto 910 operator==(const _Up& __lhs, const optional<_Tp>& __rhs) 911 -> __optional_relop_t<decltype(declval<_Up>() == declval<_Tp>())> 912 { return __rhs && __lhs == *__rhs; } 913 914 template<typename _Tp, typename _Up> 915 constexpr auto 916 operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) 917 -> __optional_relop_t<decltype(declval<_Tp>() != declval<_Up>())> 918 { return !__lhs || *__lhs != __rhs; } 919 920 template<typename _Tp, typename _Up> 921 constexpr auto 922 operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) 923 -> __optional_relop_t<decltype(declval<_Up>() != declval<_Tp>())> 924 { return !__rhs || __lhs != *__rhs; } 925 926 template<typename _Tp, typename _Up> 927 constexpr auto 928 operator<(const optional<_Tp>& __lhs, const _Up& __rhs) 929 -> __optional_relop_t<decltype(declval<_Tp>() < declval<_Up>())> 930 { return !__lhs || *__lhs < __rhs; } 931 932 template<typename _Tp, typename _Up> 933 constexpr auto 934 operator<(const _Up& __lhs, const optional<_Tp>& __rhs) 935 -> __optional_relop_t<decltype(declval<_Up>() < declval<_Tp>())> 936 { return __rhs && __lhs < *__rhs; } 937 938 template<typename _Tp, typename _Up> 939 constexpr auto 940 operator>(const optional<_Tp>& __lhs, const _Up& __rhs) 941 -> __optional_relop_t<decltype(declval<_Tp>() > declval<_Up>())> 942 { return __lhs && *__lhs > __rhs; } 943 944 template<typename _Tp, typename _Up> 945 constexpr auto 946 operator>(const _Up& __lhs, const optional<_Tp>& __rhs) 947 -> __optional_relop_t<decltype(declval<_Up>() > declval<_Tp>())> 948 { return !__rhs || __lhs > *__rhs; } 949 950 template<typename _Tp, typename _Up> 951 constexpr auto 952 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) 953 -> __optional_relop_t<decltype(declval<_Tp>() <= declval<_Up>())> 954 { return !__lhs || *__lhs <= __rhs; } 955 956 template<typename _Tp, typename _Up> 957 constexpr auto 958 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) 959 -> __optional_relop_t<decltype(declval<_Up>() <= declval<_Tp>())> 960 { return __rhs && __lhs <= *__rhs; } 961 962 template<typename _Tp, typename _Up> 963 constexpr auto 964 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) 965 -> __optional_relop_t<decltype(declval<_Tp>() >= declval<_Up>())> 966 { return __lhs && *__lhs >= __rhs; } 967 968 template<typename _Tp, typename _Up> 969 constexpr auto 970 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) 971 -> __optional_relop_t<decltype(declval<_Up>() >= declval<_Tp>())> 972 { return !__rhs || __lhs >= *__rhs; } 973 974 // Swap and creation functions. 975 976 // _GLIBCXX_RESOLVE_LIB_DEFECTS 977 // 2748. swappable traits for optionals 978 template<typename _Tp> 979 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>> 980 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 981 noexcept(noexcept(__lhs.swap(__rhs))) 982 { __lhs.swap(__rhs); } 983 984 template<typename _Tp> 985 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)> 986 swap(optional<_Tp>&, optional<_Tp>&) = delete; 987 988 template<typename _Tp> 989 constexpr optional<decay_t<_Tp>> 990 make_optional(_Tp&& __t) 991 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 992 993 template<typename _Tp, typename ..._Args> 994 constexpr optional<_Tp> 995 make_optional(_Args&&... __args) 996 { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } 997 998 template<typename _Tp, typename _Up, typename ..._Args> 999 constexpr optional<_Tp> 1000 make_optional(initializer_list<_Up> __il, _Args&&... __args) 1001 { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } 1002 1003 // Hash. 1004 1005 template<typename _Tp, typename _Up = remove_const_t<_Tp>, 1006 bool = __poison_hash<_Up>::__enable_hash_call> 1007 struct __optional_hash_call_base 1008 { 1009 size_t 1010 operator()(const optional<_Tp>& __t) const 1011 noexcept(noexcept(hash<_Up>{}(*__t))) 1012 { 1013 // We pick an arbitrary hash for disengaged optionals which hopefully 1014 // usual values of _Tp won't typically hash to. 1015 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 1016 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; 1017 } 1018 }; 1019 1020 template<typename _Tp, typename _Up> 1021 struct __optional_hash_call_base<_Tp, _Up, false> {}; 1022 1023 template<typename _Tp> 1024 struct hash<optional<_Tp>> 1025 : private __poison_hash<remove_const_t<_Tp>>, 1026 public __optional_hash_call_base<_Tp> 1027 { 1028 using result_type = size_t; 1029 using argument_type = optional<_Tp>; 1030 }; 1031 1032 /// @} 1033 1034#if __cpp_deduction_guides >= 201606 1035 template <typename _Tp> optional(_Tp) -> optional<_Tp>; 1036#endif 1037 1038_GLIBCXX_END_NAMESPACE_VERSION 1039} // namespace std 1040 1041#endif // C++17 1042 1043#endif // _GLIBCXX_OPTIONAL 1044