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