1// <optional> -*- C++ -*- 2 3// Copyright (C) 2013-2015 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 experimental/optional 26 * This is a TS C++ Library header. 27 */ 28 29#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL 30#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1 31 32/** 33 * @defgroup experimental Experimental 34 * 35 * Components specified by various Technical Specifications. 36 * 37 * As indicated by the std::experimental namespace and the header paths, 38 * the contents of these Technical Specifications are experimental and not 39 * part of the C++ standard. As such the interfaces and implementations may 40 * change in the future, and there is <STRONG> no guarantee of compatibility 41 * between different GCC releases </STRONG> for these features. 42 */ 43 44#if __cplusplus <= 201103L 45# include <bits/c++14_warning.h> 46#else 47 48#include <utility> 49#include <type_traits> 50#include <stdexcept> 51#include <new> 52#include <initializer_list> 53#include <bits/functexcept.h> 54#include <bits/functional_hash.h> 55#include <bits/enable_special_members.h> 56#include <experimental/lfts_config.h> 57 58namespace std _GLIBCXX_VISIBILITY(default) 59{ 60namespace experimental 61{ 62inline namespace fundamentals_v1 63{ 64_GLIBCXX_BEGIN_NAMESPACE_VERSION 65 66 /** 67 * @defgroup optional Optional values 68 * @ingroup experimental 69 * 70 * Class template for optional values and surrounding facilities, as 71 * described in n3793 "A proposal to add a utility class to represent 72 * optional objects (Revision 5)". 73 * 74 * @{ 75 */ 76 77#define __cpp_lib_experimental_optional 201411 78 79 // All subsequent [X.Y.n] references are against n3793. 80 81 // [X.Y.4] 82 template<typename _Tp> 83 class optional; 84 85 // [X.Y.5] 86 /// Tag type for in-place construction. 87 struct in_place_t { }; 88 89 /// Tag for in-place construction. 90 constexpr in_place_t in_place { }; 91 92 // [X.Y.6] 93 /// Tag type to disengage optional objects. 94 struct nullopt_t 95 { 96 // Do not user-declare default constructor at all for 97 // optional_value = {} syntax to work. 98 // nullopt_t() = delete; 99 100 // Used for constructing nullopt. 101 enum class _Construct { _Token }; 102 103 // Must be constexpr for nullopt_t to be literal. 104 explicit constexpr nullopt_t(_Construct) { } 105 }; 106 107 // [X.Y.6] 108 /// Tag to disengage optional objects. 109 constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; 110 111 // [X.Y.7] 112 /** 113 * @brief Exception class thrown when a disengaged optional object is 114 * dereferenced. 115 * @ingroup exceptions 116 */ 117 class bad_optional_access : public logic_error 118 { 119 public: 120 bad_optional_access() : logic_error("bad optional access") { } 121 122 // XXX This constructor is non-standard. Should not be inline 123 explicit bad_optional_access(const char* __arg) : logic_error(__arg) { } 124 125 virtual ~bad_optional_access() noexcept = default; 126 }; 127 128 void 129 __throw_bad_optional_access(const char*) 130 __attribute__((__noreturn__)); 131 132 // XXX Does not belong here. 133 inline void 134 __throw_bad_optional_access(const char* __s) 135 { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } 136 137#ifndef __cpp_lib_addressof_constexpr 138 template<typename _Tp, typename = void> 139 struct _Has_addressof_mem : std::false_type { }; 140 141 template<typename _Tp> 142 struct _Has_addressof_mem<_Tp, 143 __void_t<decltype( std::declval<const _Tp&>().operator&() )> 144 > 145 : std::true_type { }; 146 147 template<typename _Tp, typename = void> 148 struct _Has_addressof_free : std::false_type { }; 149 150 template<typename _Tp> 151 struct _Has_addressof_free<_Tp, 152 __void_t<decltype( operator&(std::declval<const _Tp&>()) )> 153 > 154 : std::true_type { }; 155 156 /** 157 * @brief Trait that detects the presence of an overloaded unary operator&. 158 * 159 * Practically speaking this detects the presence of such an operator when 160 * called on a const-qualified lvalue (i.e. 161 * declval<_Tp * const&>().operator&()). 162 */ 163 template<typename _Tp> 164 struct _Has_addressof 165 : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type 166 { }; 167 168 /** 169 * @brief An overload that attempts to take the address of an lvalue as a 170 * constant expression. Falls back to __addressof in the presence of an 171 * overloaded addressof operator (unary operator&), in which case the call 172 * will not be a constant expression. 173 */ 174 template<typename _Tp> 175 constexpr 176 enable_if_t<!_Has_addressof<_Tp>::value, _Tp*> 177 __constexpr_addressof(_Tp& __t) 178 { return &__t; } 179 180 /** 181 * @brief Fallback overload that defers to __addressof. 182 */ 183 template<typename _Tp> 184 inline 185 enable_if_t<_Has_addressof<_Tp>::value, _Tp*> 186 __constexpr_addressof(_Tp& __t) 187 { return std::__addressof(__t); } 188#endif // __cpp_lib_addressof_constexpr 189 190 /** 191 * @brief Class template that holds the necessary state for @ref optional 192 * and that has the responsibility for construction and the special members. 193 * 194 * Such a separate base class template is necessary in order to 195 * conditionally enable the special members (e.g. copy/move constructors). 196 * Note that this means that @ref _Optional_base implements the 197 * functionality for copy and move assignment, but not for converting 198 * assignment. 199 * 200 * @see optional, _Enable_special_members 201 */ 202 template<typename _Tp, bool _ShouldProvideDestructor = 203 !is_trivially_destructible<_Tp>::value> 204 class _Optional_base 205 { 206 private: 207 // Remove const to avoid prohibition of reusing object storage for 208 // const-qualified types in [3.8/9]. This is strictly internal 209 // and even optional itself is oblivious to it. 210 using _Stored_type = remove_const_t<_Tp>; 211 212 public: 213 // [X.Y.4.1] Constructors. 214 215 // Constructors for disengaged optionals. 216 constexpr _Optional_base() noexcept 217 : _M_empty{} { } 218 219 constexpr _Optional_base(nullopt_t) noexcept 220 : _Optional_base{} { } 221 222 // Constructors for engaged optionals. 223 constexpr _Optional_base(const _Tp& __t) 224 : _M_payload(__t), _M_engaged(true) { } 225 226 constexpr _Optional_base(_Tp&& __t) 227 : _M_payload(std::move(__t)), _M_engaged(true) { } 228 229 template<typename... _Args> 230 constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 231 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 232 233 template<typename _Up, typename... _Args, 234 enable_if_t<is_constructible<_Tp, 235 initializer_list<_Up>&, 236 _Args&&...>::value, 237 int>...> 238 constexpr explicit _Optional_base(in_place_t, 239 initializer_list<_Up> __il, 240 _Args&&... __args) 241 : _M_payload(__il, std::forward<_Args>(__args)...), 242 _M_engaged(true) { } 243 244 // Copy and move constructors. 245 _Optional_base(const _Optional_base& __other) 246 { 247 if (__other._M_engaged) 248 this->_M_construct(__other._M_get()); 249 } 250 251 _Optional_base(_Optional_base&& __other) 252 noexcept(is_nothrow_move_constructible<_Tp>()) 253 { 254 if (__other._M_engaged) 255 this->_M_construct(std::move(__other._M_get())); 256 } 257 258 // [X.Y.4.3] (partly) Assignment. 259 _Optional_base& 260 operator=(const _Optional_base& __other) 261 { 262 if (this->_M_engaged && __other._M_engaged) 263 this->_M_get() = __other._M_get(); 264 else 265 { 266 if (__other._M_engaged) 267 this->_M_construct(__other._M_get()); 268 else 269 this->_M_reset(); 270 } 271 272 return *this; 273 } 274 275 _Optional_base& 276 operator=(_Optional_base&& __other) 277 noexcept(__and_<is_nothrow_move_constructible<_Tp>, 278 is_nothrow_move_assignable<_Tp>>()) 279 { 280 if (this->_M_engaged && __other._M_engaged) 281 this->_M_get() = std::move(__other._M_get()); 282 else 283 { 284 if (__other._M_engaged) 285 this->_M_construct(std::move(__other._M_get())); 286 else 287 this->_M_reset(); 288 } 289 return *this; 290 } 291 292 // [X.Y.4.2] Destructor. 293 ~_Optional_base() 294 { 295 if (this->_M_engaged) 296 this->_M_payload.~_Stored_type(); 297 } 298 299 // The following functionality is also needed by optional, hence the 300 // protected accessibility. 301 protected: 302 constexpr bool _M_is_engaged() const noexcept 303 { return this->_M_engaged; } 304 305 // The _M_get operations have _M_engaged as a precondition. 306 constexpr _Tp& 307 _M_get() noexcept 308 { return _M_payload; } 309 310 constexpr const _Tp& 311 _M_get() const noexcept 312 { return _M_payload; } 313 314 // The _M_construct operation has !_M_engaged as a precondition 315 // while _M_destruct has _M_engaged as a precondition. 316 template<typename... _Args> 317 void 318 _M_construct(_Args&&... __args) 319 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 320 { 321 ::new (std::__addressof(this->_M_payload)) 322 _Stored_type(std::forward<_Args>(__args)...); 323 this->_M_engaged = true; 324 } 325 326 void 327 _M_destruct() 328 { 329 this->_M_engaged = false; 330 this->_M_payload.~_Stored_type(); 331 } 332 333 // _M_reset is a 'safe' operation with no precondition. 334 void 335 _M_reset() 336 { 337 if (this->_M_engaged) 338 this->_M_destruct(); 339 } 340 341 private: 342 struct _Empty_byte { }; 343 union { 344 _Empty_byte _M_empty; 345 _Stored_type _M_payload; 346 }; 347 bool _M_engaged = false; 348 }; 349 350 /// Partial specialization that is exactly identical to the primary template 351 /// save for not providing a destructor, to fulfill triviality requirements. 352 template<typename _Tp> 353 class _Optional_base<_Tp, false> 354 { 355 private: 356 using _Stored_type = remove_const_t<_Tp>; 357 358 public: 359 constexpr _Optional_base() noexcept 360 : _M_empty{} { } 361 362 constexpr _Optional_base(nullopt_t) noexcept 363 : _Optional_base{} { } 364 365 constexpr _Optional_base(const _Tp& __t) 366 : _M_payload(__t), _M_engaged(true) { } 367 368 constexpr _Optional_base(_Tp&& __t) 369 : _M_payload(std::move(__t)), _M_engaged(true) { } 370 371 template<typename... _Args> 372 constexpr explicit _Optional_base(in_place_t, _Args&&... __args) 373 : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { } 374 375 template<typename _Up, typename... _Args, 376 enable_if_t<is_constructible<_Tp, 377 initializer_list<_Up>&, 378 _Args&&...>::value, 379 int>...> 380 constexpr explicit _Optional_base(in_place_t, 381 initializer_list<_Up> __il, 382 _Args&&... __args) 383 : _M_payload(__il, std::forward<_Args>(__args)...), 384 _M_engaged(true) { } 385 386 _Optional_base(const _Optional_base& __other) 387 { 388 if (__other._M_engaged) 389 this->_M_construct(__other._M_get()); 390 } 391 392 _Optional_base(_Optional_base&& __other) 393 noexcept(is_nothrow_move_constructible<_Tp>()) 394 { 395 if (__other._M_engaged) 396 this->_M_construct(std::move(__other._M_get())); 397 } 398 399 _Optional_base& 400 operator=(const _Optional_base& __other) 401 { 402 if (this->_M_engaged && __other._M_engaged) 403 this->_M_get() = __other._M_get(); 404 else 405 { 406 if (__other._M_engaged) 407 this->_M_construct(__other._M_get()); 408 else 409 this->_M_reset(); 410 } 411 return *this; 412 } 413 414 _Optional_base& 415 operator=(_Optional_base&& __other) 416 noexcept(__and_<is_nothrow_move_constructible<_Tp>, 417 is_nothrow_move_assignable<_Tp>>()) 418 { 419 if (this->_M_engaged && __other._M_engaged) 420 this->_M_get() = std::move(__other._M_get()); 421 else 422 { 423 if (__other._M_engaged) 424 this->_M_construct(std::move(__other._M_get())); 425 else 426 this->_M_reset(); 427 } 428 return *this; 429 } 430 431 // Sole difference 432 // ~_Optional_base() noexcept = default; 433 434 protected: 435 constexpr bool _M_is_engaged() const noexcept 436 { return this->_M_engaged; } 437 438 _Tp& 439 _M_get() noexcept 440 { return _M_payload; } 441 442 constexpr const _Tp& 443 _M_get() const noexcept 444 { return _M_payload; } 445 446 template<typename... _Args> 447 void 448 _M_construct(_Args&&... __args) 449 noexcept(is_nothrow_constructible<_Stored_type, _Args...>()) 450 { 451 ::new (std::__addressof(this->_M_payload)) 452 _Stored_type(std::forward<_Args>(__args)...); 453 this->_M_engaged = true; 454 } 455 456 void 457 _M_destruct() 458 { 459 this->_M_engaged = false; 460 this->_M_payload.~_Stored_type(); 461 } 462 463 void 464 _M_reset() 465 { 466 if (this->_M_engaged) 467 this->_M_destruct(); 468 } 469 470 private: 471 struct _Empty_byte { }; 472 union 473 { 474 _Empty_byte _M_empty; 475 _Stored_type _M_payload; 476 }; 477 bool _M_engaged = false; 478 }; 479 480 /** 481 * @brief Class template for optional values. 482 */ 483 template<typename _Tp> 484 class optional 485 : private _Optional_base<_Tp>, 486 private _Enable_copy_move< 487 // Copy constructor. 488 is_copy_constructible<_Tp>::value, 489 // Copy assignment. 490 __and_<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>::value, 491 // Move constructor. 492 is_move_constructible<_Tp>::value, 493 // Move assignment. 494 __and_<is_move_constructible<_Tp>, is_move_assignable<_Tp>>::value, 495 // Unique tag type. 496 optional<_Tp>> 497 { 498 static_assert(__and_<__not_<is_same<remove_cv_t<_Tp>, nullopt_t>>, 499 __not_<is_same<remove_cv_t<_Tp>, in_place_t>>, 500 __not_<is_reference<_Tp>>>(), 501 "Invalid instantiation of optional<T>"); 502 503 private: 504 using _Base = _Optional_base<_Tp>; 505 506 public: 507 using value_type = _Tp; 508 509 // _Optional_base has the responsibility for construction. 510 using _Base::_Base; 511 512 // [X.Y.4.3] (partly) Assignment. 513 optional& 514 operator=(nullopt_t) noexcept 515 { 516 this->_M_reset(); 517 return *this; 518 } 519 520 template<typename _Up> 521 enable_if_t<is_same<_Tp, decay_t<_Up>>::value, optional&> 522 operator=(_Up&& __u) 523 { 524 static_assert(__and_<is_constructible<_Tp, _Up>, 525 is_assignable<_Tp&, _Up>>(), 526 "Cannot assign to value type from argument"); 527 528 if (this->_M_is_engaged()) 529 this->_M_get() = std::forward<_Up>(__u); 530 else 531 this->_M_construct(std::forward<_Up>(__u)); 532 533 return *this; 534 } 535 536 template<typename... _Args> 537 void 538 emplace(_Args&&... __args) 539 { 540 static_assert(is_constructible<_Tp, _Args&&...>(), 541 "Cannot emplace value type from arguments"); 542 543 this->_M_reset(); 544 this->_M_construct(std::forward<_Args>(__args)...); 545 } 546 547 template<typename _Up, typename... _Args> 548 enable_if_t<is_constructible<_Tp, initializer_list<_Up>&, 549 _Args&&...>::value> 550 emplace(initializer_list<_Up> __il, _Args&&... __args) 551 { 552 this->_M_reset(); 553 this->_M_construct(__il, std::forward<_Args>(__args)...); 554 } 555 556 // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base. 557 558 // [X.Y.4.4] Swap. 559 void 560 swap(optional& __other) 561 noexcept(is_nothrow_move_constructible<_Tp>() 562 && noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))) 563 { 564 using std::swap; 565 566 if (this->_M_is_engaged() && __other._M_is_engaged()) 567 swap(this->_M_get(), __other._M_get()); 568 else if (this->_M_is_engaged()) 569 { 570 __other._M_construct(std::move(this->_M_get())); 571 this->_M_destruct(); 572 } 573 else if (__other._M_is_engaged()) 574 { 575 this->_M_construct(std::move(__other._M_get())); 576 __other._M_destruct(); 577 } 578 } 579 580 // [X.Y.4.5] Observers. 581 constexpr const _Tp* 582 operator->() const 583 { 584#ifndef __cpp_lib_addressof_constexpr 585 return __constexpr_addressof(this->_M_get()); 586#else 587 return std::__addressof(this->_M_get()); 588#endif 589 } 590 591 _Tp* 592 operator->() 593 { return std::__addressof(this->_M_get()); } 594 595 constexpr const _Tp& 596 operator*() const& 597 { return this->_M_get(); } 598 599 constexpr _Tp& 600 operator*()& 601 { return this->_M_get(); } 602 603 constexpr _Tp&& 604 operator*()&& 605 { return std::move(this->_M_get()); } 606 607 constexpr const _Tp&& 608 operator*() const&& 609 { return std::move(this->_M_get()); } 610 611 constexpr explicit operator bool() const noexcept 612 { return this->_M_is_engaged(); } 613 614 constexpr const _Tp& 615 value() const& 616 { 617 return this->_M_is_engaged() 618 ? this->_M_get() 619 : (__throw_bad_optional_access("Attempt to access value of a " 620 "disengaged optional object"), 621 this->_M_get()); 622 } 623 624 constexpr _Tp& 625 value()& 626 { 627 return this->_M_is_engaged() 628 ? this->_M_get() 629 : (__throw_bad_optional_access("Attempt to access value of a " 630 "disengaged optional object"), 631 this->_M_get()); 632 } 633 634 constexpr _Tp&& 635 value()&& 636 { 637 return this->_M_is_engaged() 638 ? std::move(this->_M_get()) 639 : (__throw_bad_optional_access("Attempt to access value of a " 640 "disengaged optional object"), 641 std::move(this->_M_get())); 642 } 643 644 constexpr const _Tp&& 645 value() const&& 646 { 647 return this->_M_is_engaged() 648 ? std::move(this->_M_get()) 649 : (__throw_bad_optional_access("Attempt to access value of a " 650 "disengaged optional object"), 651 std::move(this->_M_get())); 652 } 653 654 template<typename _Up> 655 constexpr _Tp 656 value_or(_Up&& __u) const& 657 { 658 static_assert(__and_<is_copy_constructible<_Tp>, 659 is_convertible<_Up&&, _Tp>>(), 660 "Cannot return value"); 661 662 return this->_M_is_engaged() 663 ? this->_M_get() 664 : static_cast<_Tp>(std::forward<_Up>(__u)); 665 } 666 667 template<typename _Up> 668 _Tp 669 value_or(_Up&& __u) && 670 { 671 static_assert(__and_<is_move_constructible<_Tp>, 672 is_convertible<_Up&&, _Tp>>(), 673 "Cannot return value" ); 674 675 return this->_M_is_engaged() 676 ? std::move(this->_M_get()) 677 : static_cast<_Tp>(std::forward<_Up>(__u)); 678 } 679 }; 680 681 // [X.Y.8] Comparisons between optional values. 682 template<typename _Tp> 683 constexpr bool 684 operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 685 { 686 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 687 && (!__lhs || *__lhs == *__rhs); 688 } 689 690 template<typename _Tp> 691 constexpr bool 692 operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 693 { return !(__lhs == __rhs); } 694 695 template<typename _Tp> 696 constexpr bool 697 operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 698 { 699 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 700 } 701 702 template<typename _Tp> 703 constexpr bool 704 operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 705 { return __rhs < __lhs; } 706 707 template<typename _Tp> 708 constexpr bool 709 operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 710 { return !(__rhs < __lhs); } 711 712 template<typename _Tp> 713 constexpr bool 714 operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs) 715 { return !(__lhs < __rhs); } 716 717 // [X.Y.9] Comparisons with nullopt. 718 template<typename _Tp> 719 constexpr bool 720 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 721 { return !__lhs; } 722 723 template<typename _Tp> 724 constexpr bool 725 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 726 { return !__rhs; } 727 728 template<typename _Tp> 729 constexpr bool 730 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 731 { return static_cast<bool>(__lhs); } 732 733 template<typename _Tp> 734 constexpr bool 735 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 736 { return static_cast<bool>(__rhs); } 737 738 template<typename _Tp> 739 constexpr bool 740 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 741 { return false; } 742 743 template<typename _Tp> 744 constexpr bool 745 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 746 { return static_cast<bool>(__rhs); } 747 748 template<typename _Tp> 749 constexpr bool 750 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 751 { return static_cast<bool>(__lhs); } 752 753 template<typename _Tp> 754 constexpr bool 755 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 756 { return false; } 757 758 template<typename _Tp> 759 constexpr bool 760 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 761 { return !__lhs; } 762 763 template<typename _Tp> 764 constexpr bool 765 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 766 { return true; } 767 768 template<typename _Tp> 769 constexpr bool 770 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 771 { return true; } 772 773 template<typename _Tp> 774 constexpr bool 775 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 776 { return !__rhs; } 777 778 // [X.Y.10] Comparisons with value type. 779 template<typename _Tp> 780 constexpr bool 781 operator==(const optional<_Tp>& __lhs, const _Tp& __rhs) 782 { return __lhs && *__lhs == __rhs; } 783 784 template<typename _Tp> 785 constexpr bool 786 operator==(const _Tp& __lhs, const optional<_Tp>& __rhs) 787 { return __rhs && __lhs == *__rhs; } 788 789 template<typename _Tp> 790 constexpr bool 791 operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs) 792 { return !__lhs || !(*__lhs == __rhs); } 793 794 template<typename _Tp> 795 constexpr bool 796 operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs) 797 { return !__rhs || !(__lhs == *__rhs); } 798 799 template<typename _Tp> 800 constexpr bool 801 operator<(const optional<_Tp>& __lhs, const _Tp& __rhs) 802 { return !__lhs || *__lhs < __rhs; } 803 804 template<typename _Tp> 805 constexpr bool 806 operator<(const _Tp& __lhs, const optional<_Tp>& __rhs) 807 { return __rhs && __lhs < *__rhs; } 808 809 template<typename _Tp> 810 constexpr bool 811 operator>(const optional<_Tp>& __lhs, const _Tp& __rhs) 812 { return __lhs && __rhs < *__lhs; } 813 814 template<typename _Tp> 815 constexpr bool 816 operator>(const _Tp& __lhs, const optional<_Tp>& __rhs) 817 { return !__rhs || *__rhs < __lhs; } 818 819 template<typename _Tp> 820 constexpr bool 821 operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs) 822 { return !__lhs || !(__rhs < *__lhs); } 823 824 template<typename _Tp> 825 constexpr bool 826 operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs) 827 { return __rhs && !(*__rhs < __lhs); } 828 829 template<typename _Tp> 830 constexpr bool 831 operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs) 832 { return __lhs && !(*__lhs < __rhs); } 833 834 template<typename _Tp> 835 constexpr bool 836 operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs) 837 { return !__rhs || !(__lhs < *__rhs); } 838 839 // [X.Y.11] 840 template<typename _Tp> 841 inline void 842 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 843 noexcept(noexcept(__lhs.swap(__rhs))) 844 { __lhs.swap(__rhs); } 845 846 template<typename _Tp> 847 constexpr optional<decay_t<_Tp>> 848 make_optional(_Tp&& __t) 849 { return optional<decay_t<_Tp>> { std::forward<_Tp>(__t) }; } 850 851 // @} group optional 852_GLIBCXX_END_NAMESPACE_VERSION 853} // namespace fundamentals_v1 854} 855 856 // [X.Y.12] 857 template<typename _Tp> 858 struct hash<experimental::optional<_Tp>> 859 { 860 using result_type = size_t; 861 using argument_type = experimental::optional<_Tp>; 862 863 size_t 864 operator()(const experimental::optional<_Tp>& __t) const 865 noexcept(noexcept(hash<_Tp> {}(*__t))) 866 { 867 // We pick an arbitrary hash for disengaged optionals which hopefully 868 // usual values of _Tp won't typically hash to. 869 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 870 return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash; 871 } 872 }; 873} 874 875#endif // C++14 876 877#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL 878