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