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