1// <optional> -*- C++ -*- 2 3// Copyright (C) 2013-2021 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 483 _Optional_base(in_place_t, _Args&&... __args) 484 : _M_payload(in_place, std::forward<_Args>(__args)...) 485 { } 486 487 template<typename _Up, typename... _Args, 488 enable_if_t<is_constructible_v<_Tp, 489 initializer_list<_Up>&, 490 _Args...>, bool> = false> 491 constexpr explicit 492 _Optional_base(in_place_t, 493 initializer_list<_Up> __il, 494 _Args&&... __args) 495 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 496 { } 497 498 // Copy and move constructors. 499 constexpr 500 _Optional_base(const _Optional_base& __other) 501 : _M_payload(__other._M_payload._M_engaged, __other._M_payload) 502 { } 503 504 constexpr 505 _Optional_base(_Optional_base&& __other) 506 noexcept(is_nothrow_move_constructible_v<_Tp>) 507 : _M_payload(__other._M_payload._M_engaged, 508 std::move(__other._M_payload)) 509 { } 510 511 // Assignment operators. 512 _Optional_base& operator=(const _Optional_base&) = default; 513 _Optional_base& operator=(_Optional_base&&) = default; 514 515 _Optional_payload<_Tp> _M_payload; 516 }; 517 518 template<typename _Tp> 519 struct _Optional_base<_Tp, false, true> 520 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 521 { 522 // Constructors for disengaged optionals. 523 constexpr _Optional_base() = default; 524 525 // Constructors for engaged optionals. 526 template<typename... _Args, 527 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 528 constexpr explicit 529 _Optional_base(in_place_t, _Args&&... __args) 530 : _M_payload(in_place, std::forward<_Args>(__args)...) 531 { } 532 533 template<typename _Up, typename... _Args, 534 enable_if_t<is_constructible_v<_Tp, 535 initializer_list<_Up>&, 536 _Args...>, bool> = false> 537 constexpr explicit 538 _Optional_base(in_place_t, 539 initializer_list<_Up> __il, 540 _Args... __args) 541 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 542 { } 543 544 // Copy and move constructors. 545 constexpr _Optional_base(const _Optional_base& __other) 546 : _M_payload(__other._M_payload._M_engaged, __other._M_payload) 547 { } 548 549 constexpr _Optional_base(_Optional_base&& __other) = default; 550 551 // Assignment operators. 552 _Optional_base& operator=(const _Optional_base&) = default; 553 _Optional_base& operator=(_Optional_base&&) = default; 554 555 _Optional_payload<_Tp> _M_payload; 556 }; 557 558 template<typename _Tp> 559 struct _Optional_base<_Tp, true, false> 560 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 561 { 562 // Constructors for disengaged optionals. 563 constexpr _Optional_base() = default; 564 565 // Constructors for engaged optionals. 566 template<typename... _Args, 567 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 568 constexpr explicit 569 _Optional_base(in_place_t, _Args&&... __args) 570 : _M_payload(in_place, std::forward<_Args>(__args)...) 571 { } 572 573 template<typename _Up, typename... _Args, 574 enable_if_t<is_constructible_v<_Tp, 575 initializer_list<_Up>&, 576 _Args...>, bool> = false> 577 constexpr explicit 578 _Optional_base(in_place_t, 579 initializer_list<_Up> __il, 580 _Args&&... __args) 581 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 582 { } 583 584 // Copy and move constructors. 585 constexpr _Optional_base(const _Optional_base& __other) = default; 586 587 constexpr 588 _Optional_base(_Optional_base&& __other) 589 noexcept(is_nothrow_move_constructible_v<_Tp>) 590 : _M_payload(__other._M_payload._M_engaged, 591 std::move(__other._M_payload)) 592 { } 593 594 // Assignment operators. 595 _Optional_base& operator=(const _Optional_base&) = default; 596 _Optional_base& operator=(_Optional_base&&) = default; 597 598 _Optional_payload<_Tp> _M_payload; 599 }; 600 601 template<typename _Tp> 602 struct _Optional_base<_Tp, true, true> 603 : _Optional_base_impl<_Tp, _Optional_base<_Tp>> 604 { 605 // Constructors for disengaged optionals. 606 constexpr _Optional_base() = default; 607 608 // Constructors for engaged optionals. 609 template<typename... _Args, 610 enable_if_t<is_constructible_v<_Tp, _Args...>, bool> = false> 611 constexpr explicit 612 _Optional_base(in_place_t, _Args&&... __args) 613 : _M_payload(in_place, std::forward<_Args>(__args)...) 614 { } 615 616 template<typename _Up, typename... _Args, 617 enable_if_t<is_constructible_v<_Tp, 618 initializer_list<_Up>&, 619 _Args...>, bool> = false> 620 constexpr explicit 621 _Optional_base(in_place_t, 622 initializer_list<_Up> __il, 623 _Args&&... __args) 624 : _M_payload(in_place, __il, std::forward<_Args>(__args)...) 625 { } 626 627 // Copy and move constructors. 628 constexpr _Optional_base(const _Optional_base& __other) = default; 629 constexpr _Optional_base(_Optional_base&& __other) = default; 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 class optional; 640 641 template<typename _Tp, typename _Up> 642 using __converts_from_optional = 643 __or_<is_constructible<_Tp, const optional<_Up>&>, 644 is_constructible<_Tp, optional<_Up>&>, 645 is_constructible<_Tp, const optional<_Up>&&>, 646 is_constructible<_Tp, optional<_Up>&&>, 647 is_convertible<const optional<_Up>&, _Tp>, 648 is_convertible<optional<_Up>&, _Tp>, 649 is_convertible<const optional<_Up>&&, _Tp>, 650 is_convertible<optional<_Up>&&, _Tp>>; 651 652 template<typename _Tp, typename _Up> 653 using __assigns_from_optional = 654 __or_<is_assignable<_Tp&, const optional<_Up>&>, 655 is_assignable<_Tp&, optional<_Up>&>, 656 is_assignable<_Tp&, const optional<_Up>&&>, 657 is_assignable<_Tp&, optional<_Up>&&>>; 658 659 /** 660 * @brief Class template for optional values. 661 */ 662 template<typename _Tp> 663 class optional 664 : private _Optional_base<_Tp>, 665 private _Enable_copy_move< 666 // Copy constructor. 667 is_copy_constructible_v<_Tp>, 668 // Copy assignment. 669 __and_v<is_copy_constructible<_Tp>, is_copy_assignable<_Tp>>, 670 // Move constructor. 671 is_move_constructible_v<_Tp>, 672 // Move assignment. 673 __and_v<is_move_constructible<_Tp>, is_move_assignable<_Tp>>, 674 // Unique tag type. 675 optional<_Tp>> 676 { 677 static_assert(!is_same_v<remove_cv_t<_Tp>, nullopt_t>); 678 static_assert(!is_same_v<remove_cv_t<_Tp>, in_place_t>); 679 static_assert(!is_reference_v<_Tp>); 680 681 private: 682 using _Base = _Optional_base<_Tp>; 683 684 // SFINAE helpers 685 template<typename _Up> 686 using __not_self = __not_<is_same<optional, __remove_cvref_t<_Up>>>; 687 template<typename _Up> 688 using __not_tag = __not_<is_same<in_place_t, __remove_cvref_t<_Up>>>; 689 template<typename... _Cond> 690 using _Requires = enable_if_t<__and_v<_Cond...>, bool>; 691 692 public: 693 using value_type = _Tp; 694 695 constexpr optional() noexcept { } 696 697 constexpr optional(nullopt_t) noexcept { } 698 699 // Converting constructors for engaged optionals. 700 template<typename _Up = _Tp, 701 _Requires<__not_self<_Up>, __not_tag<_Up>, 702 is_constructible<_Tp, _Up>, 703 is_convertible<_Up, _Tp>> = true> 704 constexpr 705 optional(_Up&& __t) 706 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 707 : _Base(std::in_place, std::forward<_Up>(__t)) { } 708 709 template<typename _Up = _Tp, 710 _Requires<__not_self<_Up>, __not_tag<_Up>, 711 is_constructible<_Tp, _Up>, 712 __not_<is_convertible<_Up, _Tp>>> = false> 713 explicit constexpr 714 optional(_Up&& __t) 715 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 716 : _Base(std::in_place, std::forward<_Up>(__t)) { } 717 718 template<typename _Up, 719 _Requires<__not_<is_same<_Tp, _Up>>, 720 is_constructible<_Tp, const _Up&>, 721 is_convertible<const _Up&, _Tp>, 722 __not_<__converts_from_optional<_Tp, _Up>>> = true> 723 constexpr 724 optional(const optional<_Up>& __t) 725 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) 726 { 727 if (__t) 728 emplace(*__t); 729 } 730 731 template<typename _Up, 732 _Requires<__not_<is_same<_Tp, _Up>>, 733 is_constructible<_Tp, const _Up&>, 734 __not_<is_convertible<const _Up&, _Tp>>, 735 __not_<__converts_from_optional<_Tp, _Up>>> = false> 736 explicit constexpr 737 optional(const optional<_Up>& __t) 738 noexcept(is_nothrow_constructible_v<_Tp, const _Up&>) 739 { 740 if (__t) 741 emplace(*__t); 742 } 743 744 template<typename _Up, 745 _Requires<__not_<is_same<_Tp, _Up>>, 746 is_constructible<_Tp, _Up>, 747 is_convertible<_Up, _Tp>, 748 __not_<__converts_from_optional<_Tp, _Up>>> = true> 749 constexpr 750 optional(optional<_Up>&& __t) 751 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 752 { 753 if (__t) 754 emplace(std::move(*__t)); 755 } 756 757 template<typename _Up, 758 _Requires<__not_<is_same<_Tp, _Up>>, 759 is_constructible<_Tp, _Up>, 760 __not_<is_convertible<_Up, _Tp>>, 761 __not_<__converts_from_optional<_Tp, _Up>>> = false> 762 explicit constexpr 763 optional(optional<_Up>&& __t) 764 noexcept(is_nothrow_constructible_v<_Tp, _Up>) 765 { 766 if (__t) 767 emplace(std::move(*__t)); 768 } 769 770 template<typename... _Args, 771 _Requires<is_constructible<_Tp, _Args...>> = false> 772 explicit constexpr 773 optional(in_place_t, _Args&&... __args) 774 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 775 : _Base(std::in_place, std::forward<_Args>(__args)...) { } 776 777 template<typename _Up, typename... _Args, 778 _Requires<is_constructible<_Tp, 779 initializer_list<_Up>&, 780 _Args...>> = false> 781 explicit constexpr 782 optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 783 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, 784 _Args...>) 785 : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } 786 787 788 // Assignment operators. 789 optional& 790 operator=(nullopt_t) noexcept 791 { 792 this->_M_reset(); 793 return *this; 794 } 795 796 template<typename _Up = _Tp> 797 enable_if_t<__and_v<__not_self<_Up>, 798 __not_<__and_<is_scalar<_Tp>, 799 is_same<_Tp, decay_t<_Up>>>>, 800 is_constructible<_Tp, _Up>, 801 is_assignable<_Tp&, _Up>>, 802 optional&> 803 operator=(_Up&& __u) 804 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, 805 is_nothrow_assignable<_Tp&, _Up>>) 806 { 807 if (this->_M_is_engaged()) 808 this->_M_get() = std::forward<_Up>(__u); 809 else 810 this->_M_construct(std::forward<_Up>(__u)); 811 812 return *this; 813 } 814 815 template<typename _Up> 816 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, 817 is_constructible<_Tp, const _Up&>, 818 is_assignable<_Tp&, const _Up&>, 819 __not_<__converts_from_optional<_Tp, _Up>>, 820 __not_<__assigns_from_optional<_Tp, _Up>>>, 821 optional&> 822 operator=(const optional<_Up>& __u) 823 noexcept(__and_v<is_nothrow_constructible<_Tp, const _Up&>, 824 is_nothrow_assignable<_Tp&, const _Up&>>) 825 { 826 if (__u) 827 { 828 if (this->_M_is_engaged()) 829 this->_M_get() = *__u; 830 else 831 this->_M_construct(*__u); 832 } 833 else 834 { 835 this->_M_reset(); 836 } 837 return *this; 838 } 839 840 template<typename _Up> 841 enable_if_t<__and_v<__not_<is_same<_Tp, _Up>>, 842 is_constructible<_Tp, _Up>, 843 is_assignable<_Tp&, _Up>, 844 __not_<__converts_from_optional<_Tp, _Up>>, 845 __not_<__assigns_from_optional<_Tp, _Up>>>, 846 optional&> 847 operator=(optional<_Up>&& __u) 848 noexcept(__and_v<is_nothrow_constructible<_Tp, _Up>, 849 is_nothrow_assignable<_Tp&, _Up>>) 850 { 851 if (__u) 852 { 853 if (this->_M_is_engaged()) 854 this->_M_get() = std::move(*__u); 855 else 856 this->_M_construct(std::move(*__u)); 857 } 858 else 859 { 860 this->_M_reset(); 861 } 862 863 return *this; 864 } 865 866 template<typename... _Args> 867 enable_if_t<is_constructible_v<_Tp, _Args...>, _Tp&> 868 emplace(_Args&&... __args) 869 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 870 { 871 this->_M_reset(); 872 this->_M_construct(std::forward<_Args>(__args)...); 873 return this->_M_get(); 874 } 875 876 template<typename _Up, typename... _Args> 877 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 878 _Tp&> 879 emplace(initializer_list<_Up> __il, _Args&&... __args) 880 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, 881 _Args...>) 882 { 883 this->_M_reset(); 884 this->_M_construct(__il, std::forward<_Args>(__args)...); 885 return this->_M_get(); 886 } 887 888 // Destructor is implicit, implemented in _Optional_base. 889 890 // Swap. 891 void 892 swap(optional& __other) 893 noexcept(is_nothrow_move_constructible_v<_Tp> 894 && is_nothrow_swappable_v<_Tp>) 895 { 896 using std::swap; 897 898 if (this->_M_is_engaged() && __other._M_is_engaged()) 899 swap(this->_M_get(), __other._M_get()); 900 else if (this->_M_is_engaged()) 901 { 902 __other._M_construct(std::move(this->_M_get())); 903 this->_M_destruct(); 904 } 905 else if (__other._M_is_engaged()) 906 { 907 this->_M_construct(std::move(__other._M_get())); 908 __other._M_destruct(); 909 } 910 } 911 912 // Observers. 913 constexpr const _Tp* 914 operator->() const noexcept 915 { return std::__addressof(this->_M_get()); } 916 917 constexpr _Tp* 918 operator->() noexcept 919 { return std::__addressof(this->_M_get()); } 920 921 constexpr const _Tp& 922 operator*() const& noexcept 923 { return this->_M_get(); } 924 925 constexpr _Tp& 926 operator*()& noexcept 927 { return this->_M_get(); } 928 929 constexpr _Tp&& 930 operator*()&& noexcept 931 { return std::move(this->_M_get()); } 932 933 constexpr const _Tp&& 934 operator*() const&& noexcept 935 { return std::move(this->_M_get()); } 936 937 constexpr explicit operator bool() const noexcept 938 { return this->_M_is_engaged(); } 939 940 constexpr bool has_value() const noexcept 941 { return this->_M_is_engaged(); } 942 943 constexpr const _Tp& 944 value() const& 945 { 946 return this->_M_is_engaged() 947 ? this->_M_get() 948 : (__throw_bad_optional_access(), this->_M_get()); 949 } 950 951 constexpr _Tp& 952 value()& 953 { 954 return this->_M_is_engaged() 955 ? this->_M_get() 956 : (__throw_bad_optional_access(), this->_M_get()); 957 } 958 959 constexpr _Tp&& 960 value()&& 961 { 962 return this->_M_is_engaged() 963 ? std::move(this->_M_get()) 964 : (__throw_bad_optional_access(), std::move(this->_M_get())); 965 } 966 967 constexpr const _Tp&& 968 value() const&& 969 { 970 return this->_M_is_engaged() 971 ? std::move(this->_M_get()) 972 : (__throw_bad_optional_access(), std::move(this->_M_get())); 973 } 974 975 template<typename _Up> 976 constexpr _Tp 977 value_or(_Up&& __u) const& 978 { 979 static_assert(is_copy_constructible_v<_Tp>); 980 static_assert(is_convertible_v<_Up&&, _Tp>); 981 982 return this->_M_is_engaged() 983 ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u)); 984 } 985 986 template<typename _Up> 987 constexpr _Tp 988 value_or(_Up&& __u) && 989 { 990 static_assert(is_move_constructible_v<_Tp>); 991 static_assert(is_convertible_v<_Up&&, _Tp>); 992 993 return this->_M_is_engaged() 994 ? std::move(this->_M_get()) 995 : static_cast<_Tp>(std::forward<_Up>(__u)); 996 } 997 998 void reset() noexcept { this->_M_reset(); } 999 }; 1000 1001 template<typename _Tp> 1002 using __optional_relop_t = 1003 enable_if_t<is_convertible<_Tp, bool>::value, bool>; 1004 1005 template<typename _Tp, typename _Up> 1006 using __optional_eq_t = __optional_relop_t< 1007 decltype(std::declval<const _Tp&>() == std::declval<const _Up&>()) 1008 >; 1009 1010 template<typename _Tp, typename _Up> 1011 using __optional_ne_t = __optional_relop_t< 1012 decltype(std::declval<const _Tp&>() != std::declval<const _Up&>()) 1013 >; 1014 1015 template<typename _Tp, typename _Up> 1016 using __optional_lt_t = __optional_relop_t< 1017 decltype(std::declval<const _Tp&>() < std::declval<const _Up&>()) 1018 >; 1019 1020 template<typename _Tp, typename _Up> 1021 using __optional_gt_t = __optional_relop_t< 1022 decltype(std::declval<const _Tp&>() > std::declval<const _Up&>()) 1023 >; 1024 1025 template<typename _Tp, typename _Up> 1026 using __optional_le_t = __optional_relop_t< 1027 decltype(std::declval<const _Tp&>() <= std::declval<const _Up&>()) 1028 >; 1029 1030 template<typename _Tp, typename _Up> 1031 using __optional_ge_t = __optional_relop_t< 1032 decltype(std::declval<const _Tp&>() >= std::declval<const _Up&>()) 1033 >; 1034 1035 // Comparisons between optional values. 1036 template<typename _Tp, typename _Up> 1037 constexpr auto 1038 operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1039 -> __optional_eq_t<_Tp, _Up> 1040 { 1041 return static_cast<bool>(__lhs) == static_cast<bool>(__rhs) 1042 && (!__lhs || *__lhs == *__rhs); 1043 } 1044 1045 template<typename _Tp, typename _Up> 1046 constexpr auto 1047 operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1048 -> __optional_ne_t<_Tp, _Up> 1049 { 1050 return static_cast<bool>(__lhs) != static_cast<bool>(__rhs) 1051 || (static_cast<bool>(__lhs) && *__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_lt_t<_Tp, _Up> 1058 { 1059 return static_cast<bool>(__rhs) && (!__lhs || *__lhs < *__rhs); 1060 } 1061 1062 template<typename _Tp, typename _Up> 1063 constexpr auto 1064 operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1065 -> __optional_gt_t<_Tp, _Up> 1066 { 1067 return static_cast<bool>(__lhs) && (!__rhs || *__lhs > *__rhs); 1068 } 1069 1070 template<typename _Tp, typename _Up> 1071 constexpr auto 1072 operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1073 -> __optional_le_t<_Tp, _Up> 1074 { 1075 return !__lhs || (static_cast<bool>(__rhs) && *__lhs <= *__rhs); 1076 } 1077 1078 template<typename _Tp, typename _Up> 1079 constexpr auto 1080 operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) 1081 -> __optional_ge_t<_Tp, _Up> 1082 { 1083 return !__rhs || (static_cast<bool>(__lhs) && *__lhs >= *__rhs); 1084 } 1085 1086#ifdef __cpp_lib_three_way_comparison 1087 template<typename _Tp, three_way_comparable_with<_Tp> _Up> 1088 constexpr compare_three_way_result_t<_Tp, _Up> 1089 operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) 1090 { 1091 return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); 1092 } 1093#endif 1094 1095 // Comparisons with nullopt. 1096 template<typename _Tp> 1097 constexpr bool 1098 operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept 1099 { return !__lhs; } 1100 1101#ifdef __cpp_lib_three_way_comparison 1102 template<typename _Tp> 1103 constexpr strong_ordering 1104 operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept 1105 { return bool(__x) <=> false; } 1106#else 1107 template<typename _Tp> 1108 constexpr bool 1109 operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept 1110 { return !__rhs; } 1111 1112 template<typename _Tp> 1113 constexpr bool 1114 operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept 1115 { return static_cast<bool>(__lhs); } 1116 1117 template<typename _Tp> 1118 constexpr bool 1119 operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept 1120 { return static_cast<bool>(__rhs); } 1121 1122 template<typename _Tp> 1123 constexpr bool 1124 operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 1125 { return false; } 1126 1127 template<typename _Tp> 1128 constexpr bool 1129 operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept 1130 { return static_cast<bool>(__rhs); } 1131 1132 template<typename _Tp> 1133 constexpr bool 1134 operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept 1135 { return static_cast<bool>(__lhs); } 1136 1137 template<typename _Tp> 1138 constexpr bool 1139 operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 1140 { return false; } 1141 1142 template<typename _Tp> 1143 constexpr bool 1144 operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept 1145 { return !__lhs; } 1146 1147 template<typename _Tp> 1148 constexpr bool 1149 operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept 1150 { return true; } 1151 1152 template<typename _Tp> 1153 constexpr bool 1154 operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept 1155 { return true; } 1156 1157 template<typename _Tp> 1158 constexpr bool 1159 operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept 1160 { return !__rhs; } 1161#endif // three-way-comparison 1162 1163 // Comparisons with value type. 1164 template<typename _Tp, typename _Up> 1165 constexpr auto 1166 operator==(const optional<_Tp>& __lhs, const _Up& __rhs) 1167 -> __optional_eq_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_eq_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_ne_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_ne_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_lt_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_lt_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_gt_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_gt_t<_Up, _Tp> 1210 { return !__rhs || __lhs > *__rhs; } 1211 1212 template<typename _Tp, typename _Up> 1213 constexpr auto 1214 operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) 1215 -> __optional_le_t<_Tp, _Up> 1216 { return !__lhs || *__lhs <= __rhs; } 1217 1218 template<typename _Tp, typename _Up> 1219 constexpr auto 1220 operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) 1221 -> __optional_le_t<_Up, _Tp> 1222 { return __rhs && __lhs <= *__rhs; } 1223 1224 template<typename _Tp, typename _Up> 1225 constexpr auto 1226 operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) 1227 -> __optional_ge_t<_Tp, _Up> 1228 { return __lhs && *__lhs >= __rhs; } 1229 1230 template<typename _Tp, typename _Up> 1231 constexpr auto 1232 operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) 1233 -> __optional_ge_t<_Up, _Tp> 1234 { return !__rhs || __lhs >= *__rhs; } 1235 1236#ifdef __cpp_lib_three_way_comparison 1237 template<typename _Tp> 1238 inline constexpr bool __is_optional_v = false; 1239 template<typename _Tp> 1240 inline constexpr bool __is_optional_v<optional<_Tp>> = true; 1241 1242 template<typename _Tp, typename _Up> 1243 requires (!__is_optional_v<_Up>) 1244 && three_way_comparable_with<_Tp, _Up> 1245 constexpr compare_three_way_result_t<_Tp, _Up> 1246 operator<=>(const optional<_Tp>& __x, const _Up& __v) 1247 { return bool(__x) ? *__x <=> __v : strong_ordering::less; } 1248#endif 1249 1250 // Swap and creation functions. 1251 1252 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1253 // 2748. swappable traits for optionals 1254 template<typename _Tp> 1255 inline enable_if_t<is_move_constructible_v<_Tp> && is_swappable_v<_Tp>> 1256 swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) 1257 noexcept(noexcept(__lhs.swap(__rhs))) 1258 { __lhs.swap(__rhs); } 1259 1260 template<typename _Tp> 1261 enable_if_t<!(is_move_constructible_v<_Tp> && is_swappable_v<_Tp>)> 1262 swap(optional<_Tp>&, optional<_Tp>&) = delete; 1263 1264 template<typename _Tp> 1265 constexpr 1266 enable_if_t<is_constructible_v<decay_t<_Tp>, _Tp>, 1267 optional<decay_t<_Tp>>> 1268 make_optional(_Tp&& __t) 1269 noexcept(is_nothrow_constructible_v<optional<decay_t<_Tp>>, _Tp>) 1270 { return optional<decay_t<_Tp>>{ std::forward<_Tp>(__t) }; } 1271 1272 template<typename _Tp, typename... _Args> 1273 constexpr 1274 enable_if_t<is_constructible_v<_Tp, _Args...>, 1275 optional<_Tp>> 1276 make_optional(_Args&&... __args) 1277 noexcept(is_nothrow_constructible_v<_Tp, _Args...>) 1278 { return optional<_Tp>{ in_place, std::forward<_Args>(__args)... }; } 1279 1280 template<typename _Tp, typename _Up, typename... _Args> 1281 constexpr 1282 enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, 1283 optional<_Tp>> 1284 make_optional(initializer_list<_Up> __il, _Args&&... __args) 1285 noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) 1286 { return optional<_Tp>{ in_place, __il, std::forward<_Args>(__args)... }; } 1287 1288 // Hash. 1289 1290 template<typename _Tp, typename _Up = remove_const_t<_Tp>, 1291 bool = __poison_hash<_Up>::__enable_hash_call> 1292 struct __optional_hash_call_base 1293 { 1294 size_t 1295 operator()(const optional<_Tp>& __t) const 1296 noexcept(noexcept(hash<_Up>{}(*__t))) 1297 { 1298 // We pick an arbitrary hash for disengaged optionals which hopefully 1299 // usual values of _Tp won't typically hash to. 1300 constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333); 1301 return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; 1302 } 1303 }; 1304 1305 template<typename _Tp, typename _Up> 1306 struct __optional_hash_call_base<_Tp, _Up, false> {}; 1307 1308 template<typename _Tp> 1309 struct hash<optional<_Tp>> 1310 : private __poison_hash<remove_const_t<_Tp>>, 1311 public __optional_hash_call_base<_Tp> 1312 { 1313 using result_type [[__deprecated__]] = size_t; 1314 using argument_type [[__deprecated__]] = optional<_Tp>; 1315 }; 1316 1317 template<typename _Tp> 1318 struct __is_fast_hash<hash<optional<_Tp>>> : __is_fast_hash<hash<_Tp>> 1319 { }; 1320 1321 /// @} 1322 1323#if __cpp_deduction_guides >= 201606 1324 template <typename _Tp> optional(_Tp) -> optional<_Tp>; 1325#endif 1326 1327_GLIBCXX_END_NAMESPACE_VERSION 1328} // namespace std 1329 1330#endif // C++17 1331 1332#endif // _GLIBCXX_OPTIONAL 1333