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