1 // -*- C++ -*- 2 //===-------------------------- optional ----------------------------------===// 3 // 4 // The LLVM Compiler Infrastructure 5 // 6 // This file is dual licensed under the MIT and the University of Illinois Open 7 // Source Licenses. See LICENSE.TXT for details. 8 // 9 //===----------------------------------------------------------------------===// 10 11 #ifndef _LIBCPP_OPTIONAL 12 #define _LIBCPP_OPTIONAL 13 14 /* 15 optional synopsis 16 17 // C++1y 18 19 #include <initializer_list> 20 21 namespace std { namespace experimental { 22 23 // optional for object types 24 template <class T> 25 class optional 26 { 27 public: 28 typedef T value_type; 29 30 // constructors 31 constexpr optional() noexcept; 32 constexpr optional(nullopt_t) noexcept; 33 optional(const optional&); 34 optional(optional&&) noexcept(is_nothrow_move_constructible<T>::value); 35 constexpr optional(const T&); 36 constexpr optional(T&&); 37 template <class... Args> constexpr explicit optional(in_place_t, Args&&...); 38 template <class U, class... Args> 39 constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...); 40 41 // destructor 42 ~optional(); 43 44 // assignment 45 optional& operator=(nullopt_t) noexcept; 46 optional& operator=(const optional&); 47 optional& operator=(optional&&) 48 noexcept(is_nothrow_move_assignable<T>::value && 49 is_nothrow_move_constructible<T>::value); 50 template <class U> optional& operator=(U&&); 51 template <class... Args> void emplace(Args&&...); 52 template <class U, class... Args> void emplace(initializer_list<U>, Args&&...); 53 54 // swap 55 void swap(optional&) 56 noexcept(is_nothrow_move_constructible<T>::value && 57 noexcept(swap(declval<T&>(), declval<T&>()))); 58 59 // observers 60 constexpr T const* operator->() const; 61 T* operator->(); 62 constexpr T const& operator*() const; 63 T& operator*(); 64 constexpr explicit operator bool() const noexcept; 65 constexpr T const& value() const; 66 T& value(); 67 template <class U> constexpr T value_or(U&&) const&; 68 template <class U> T value_or(U&&) &&; 69 }; 70 71 // In-place construction 72 struct in_place_t{}; 73 constexpr in_place_t in_place{}; 74 75 // Disengaged state indicator 76 struct nullopt_t{see below}; 77 constexpr nullopt_t nullopt(unspecified); 78 79 // class bad_optional_access 80 class bad_optional_access 81 : public logic_error 82 { 83 public: 84 explicit bad_optional_access(const string& what_arg); 85 explicit bad_optional_access(const char* what_arg); 86 }; 87 88 // Relational operators 89 template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&); 90 template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&); 91 92 // Comparison with nullopt 93 template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 94 template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 95 template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 96 template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 97 98 // Comparison with T 99 template <class T> constexpr bool operator==(const optional<T>&, const T&); 100 template <class T> constexpr bool operator==(const T&, const optional<T>&); 101 template <class T> constexpr bool operator<(const optional<T>&, const T&); 102 template <class T> constexpr bool operator<(const T&, const optional<T>&); 103 104 // Specialized algorithms 105 template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below); 106 template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&); 107 108 // hash support 109 template <class T> struct hash; 110 template <class T> struct hash<optional<T>>; 111 112 }} // std::experimental 113 114 */ 115 116 #include <__config> 117 #include <functional> 118 #include <stdexcept> 119 120 namespace std { namespace experimental { 121 122 class _LIBCPP_EXCEPTION_ABI bad_optional_access 123 : public logic_error 124 { 125 public: 126 #if _LIBCPP_STD_VER > 11 127 _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const string& __arg) 128 : logic_error(__arg) {} 129 _LIBCPP_INLINE_VISIBILITY explicit bad_optional_access(const char* __arg) 130 : logic_error(__arg) {} 131 _LIBCPP_INLINE_VISIBILITY bad_optional_access(const bad_optional_access&) noexcept = default; 132 _LIBCPP_INLINE_VISIBILITY bad_optional_access& operator=(const bad_optional_access&) noexcept = default; 133 #else 134 private: 135 bad_optional_access(const bad_optional_access&); 136 bad_optional_access& operator=(const bad_optional_access&); 137 public: 138 #endif // _LIBCPP_STD_VER > 11 139 // Get the key function ~bad_optional_access() into the dylib even if not compiling for C++1y 140 virtual ~bad_optional_access() _NOEXCEPT; 141 }; 142 143 }} // std::experimental 144 145 #if _LIBCPP_STD_VER > 11 146 147 #include <initializer_list> 148 #include <type_traits> 149 #include <new> 150 #include <__functional_base> 151 152 #include <__undef_min_max> 153 154 #ifdef _LIBCPP_DEBUG 155 # include <__debug> 156 #else 157 # define _LIBCPP_ASSERT(x, m) ((void)0) 158 #endif 159 160 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 161 #pragma GCC system_header 162 #endif 163 164 namespace std { namespace experimental { inline namespace __library_fundamentals_v1 { 165 166 struct in_place_t {}; 167 constexpr in_place_t in_place{}; 168 169 struct nullopt_t 170 { 171 explicit constexpr nullopt_t(int) noexcept {} 172 }; 173 174 constexpr nullopt_t nullopt{0}; 175 176 template <class _Tp, bool = is_trivially_destructible<_Tp>::value> 177 class __optional_storage 178 { 179 protected: 180 typedef _Tp value_type; 181 union 182 { 183 char __null_state_; 184 value_type __val_; 185 }; 186 bool __engaged_ = false; 187 188 _LIBCPP_INLINE_VISIBILITY 189 ~__optional_storage() 190 { 191 if (__engaged_) 192 __val_.~value_type(); 193 } 194 195 _LIBCPP_INLINE_VISIBILITY 196 constexpr __optional_storage() noexcept 197 : __null_state_('\0') {} 198 199 _LIBCPP_INLINE_VISIBILITY 200 __optional_storage(const __optional_storage& __x) 201 : __engaged_(__x.__engaged_) 202 { 203 if (__engaged_) 204 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); 205 } 206 207 _LIBCPP_INLINE_VISIBILITY 208 __optional_storage(__optional_storage&& __x) 209 noexcept(is_nothrow_move_constructible<value_type>::value) 210 : __engaged_(__x.__engaged_) 211 { 212 if (__engaged_) 213 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); 214 } 215 216 _LIBCPP_INLINE_VISIBILITY 217 constexpr __optional_storage(const value_type& __v) 218 : __val_(__v), 219 __engaged_(true) {} 220 221 _LIBCPP_INLINE_VISIBILITY 222 constexpr __optional_storage(value_type&& __v) 223 : __val_(_VSTD::move(__v)), 224 __engaged_(true) {} 225 226 template <class... _Args> 227 _LIBCPP_INLINE_VISIBILITY 228 constexpr 229 explicit __optional_storage(in_place_t, _Args&&... __args) 230 : __val_(_VSTD::forward<_Args>(__args)...), 231 __engaged_(true) {} 232 }; 233 234 template <class _Tp> 235 class __optional_storage<_Tp, true> 236 { 237 protected: 238 typedef _Tp value_type; 239 union 240 { 241 char __null_state_; 242 value_type __val_; 243 }; 244 bool __engaged_ = false; 245 246 _LIBCPP_INLINE_VISIBILITY 247 constexpr __optional_storage() noexcept 248 : __null_state_('\0') {} 249 250 _LIBCPP_INLINE_VISIBILITY 251 __optional_storage(const __optional_storage& __x) 252 : __engaged_(__x.__engaged_) 253 { 254 if (__engaged_) 255 ::new(_VSTD::addressof(__val_)) value_type(__x.__val_); 256 } 257 258 _LIBCPP_INLINE_VISIBILITY 259 __optional_storage(__optional_storage&& __x) 260 noexcept(is_nothrow_move_constructible<value_type>::value) 261 : __engaged_(__x.__engaged_) 262 { 263 if (__engaged_) 264 ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_)); 265 } 266 267 _LIBCPP_INLINE_VISIBILITY 268 constexpr __optional_storage(const value_type& __v) 269 : __val_(__v), 270 __engaged_(true) {} 271 272 _LIBCPP_INLINE_VISIBILITY 273 constexpr __optional_storage(value_type&& __v) 274 : __val_(_VSTD::move(__v)), 275 __engaged_(true) {} 276 277 template <class... _Args> 278 _LIBCPP_INLINE_VISIBILITY 279 constexpr 280 explicit __optional_storage(in_place_t, _Args&&... __args) 281 : __val_(_VSTD::forward<_Args>(__args)...), 282 __engaged_(true) {} 283 }; 284 285 template <class _Tp> 286 class optional 287 : private __optional_storage<_Tp> 288 { 289 typedef __optional_storage<_Tp> __base; 290 public: 291 typedef _Tp value_type; 292 293 static_assert(!is_reference<value_type>::value, 294 "Instantiation of optional with a reference type is ill-formed."); 295 static_assert(!is_same<typename remove_cv<value_type>::type, in_place_t>::value, 296 "Instantiation of optional with a in_place_t type is ill-formed."); 297 static_assert(!is_same<typename remove_cv<value_type>::type, nullopt_t>::value, 298 "Instantiation of optional with a nullopt_t type is ill-formed."); 299 static_assert(is_object<value_type>::value, 300 "Instantiation of optional with a non-object type is undefined behavior."); 301 static_assert(is_nothrow_destructible<value_type>::value, 302 "Instantiation of optional with an object type that is not noexcept destructible is undefined behavior."); 303 304 _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {} 305 _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default; 306 _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default; 307 _LIBCPP_INLINE_VISIBILITY ~optional() = default; 308 _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {} 309 _LIBCPP_INLINE_VISIBILITY constexpr optional(const value_type& __v) 310 : __base(__v) {} 311 _LIBCPP_INLINE_VISIBILITY constexpr optional(value_type&& __v) 312 : __base(_VSTD::move(__v)) {} 313 314 template <class... _Args, 315 class = typename enable_if 316 < 317 is_constructible<value_type, _Args...>::value 318 >::type 319 > 320 _LIBCPP_INLINE_VISIBILITY 321 constexpr 322 explicit optional(in_place_t, _Args&&... __args) 323 : __base(in_place, _VSTD::forward<_Args>(__args)...) {} 324 325 template <class _Up, class... _Args, 326 class = typename enable_if 327 < 328 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value 329 >::type 330 > 331 _LIBCPP_INLINE_VISIBILITY 332 constexpr 333 explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) 334 : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {} 335 336 _LIBCPP_INLINE_VISIBILITY 337 optional& operator=(nullopt_t) noexcept 338 { 339 if (this->__engaged_) 340 { 341 this->__val_.~value_type(); 342 this->__engaged_ = false; 343 } 344 return *this; 345 } 346 347 _LIBCPP_INLINE_VISIBILITY 348 optional& 349 operator=(const optional& __opt) 350 { 351 if (this->__engaged_ == __opt.__engaged_) 352 { 353 if (this->__engaged_) 354 this->__val_ = __opt.__val_; 355 } 356 else 357 { 358 if (this->__engaged_) 359 this->__val_.~value_type(); 360 else 361 ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_); 362 this->__engaged_ = __opt.__engaged_; 363 } 364 return *this; 365 } 366 367 _LIBCPP_INLINE_VISIBILITY 368 optional& 369 operator=(optional&& __opt) 370 noexcept(is_nothrow_move_assignable<value_type>::value && 371 is_nothrow_move_constructible<value_type>::value) 372 { 373 if (this->__engaged_ == __opt.__engaged_) 374 { 375 if (this->__engaged_) 376 this->__val_ = _VSTD::move(__opt.__val_); 377 } 378 else 379 { 380 if (this->__engaged_) 381 this->__val_.~value_type(); 382 else 383 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); 384 this->__engaged_ = __opt.__engaged_; 385 } 386 return *this; 387 } 388 389 template <class _Up, 390 class = typename enable_if 391 < 392 is_same<typename remove_reference<_Up>::type, value_type>::value && 393 is_constructible<value_type, _Up>::value && 394 is_assignable<value_type&, _Up>::value 395 >::type 396 > 397 _LIBCPP_INLINE_VISIBILITY 398 optional& 399 operator=(_Up&& __v) 400 { 401 if (this->__engaged_) 402 this->__val_ = _VSTD::forward<_Up>(__v); 403 else 404 { 405 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v)); 406 this->__engaged_ = true; 407 } 408 return *this; 409 } 410 411 template <class... _Args, 412 class = typename enable_if 413 < 414 is_constructible<value_type, _Args...>::value 415 >::type 416 > 417 _LIBCPP_INLINE_VISIBILITY 418 void 419 emplace(_Args&&... __args) 420 { 421 *this = nullopt; 422 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...); 423 this->__engaged_ = true; 424 } 425 426 template <class _Up, class... _Args, 427 class = typename enable_if 428 < 429 is_constructible<value_type, initializer_list<_Up>&, _Args...>::value 430 >::type 431 > 432 _LIBCPP_INLINE_VISIBILITY 433 void 434 emplace(initializer_list<_Up> __il, _Args&&... __args) 435 { 436 *this = nullopt; 437 ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...); 438 this->__engaged_ = true; 439 } 440 441 _LIBCPP_INLINE_VISIBILITY 442 void 443 swap(optional& __opt) 444 noexcept(is_nothrow_move_constructible<value_type>::value && 445 __is_nothrow_swappable<value_type>::value) 446 { 447 using _VSTD::swap; 448 if (this->__engaged_ == __opt.__engaged_) 449 { 450 if (this->__engaged_) 451 swap(this->__val_, __opt.__val_); 452 } 453 else 454 { 455 if (this->__engaged_) 456 { 457 ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_)); 458 this->__val_.~value_type(); 459 } 460 else 461 { 462 ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_)); 463 __opt.__val_.~value_type(); 464 } 465 swap(this->__engaged_, __opt.__engaged_); 466 } 467 } 468 469 _LIBCPP_INLINE_VISIBILITY 470 constexpr 471 value_type const* 472 operator->() const 473 { 474 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); 475 return __operator_arrow(__has_operator_addressof<value_type>{}); 476 } 477 478 _LIBCPP_INLINE_VISIBILITY 479 value_type* 480 operator->() 481 { 482 _LIBCPP_ASSERT(this->__engaged_, "optional operator-> called for disengaged value"); 483 return _VSTD::addressof(this->__val_); 484 } 485 486 _LIBCPP_INLINE_VISIBILITY 487 constexpr 488 const value_type& 489 operator*() const 490 { 491 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); 492 return this->__val_; 493 } 494 495 _LIBCPP_INLINE_VISIBILITY 496 value_type& 497 operator*() 498 { 499 _LIBCPP_ASSERT(this->__engaged_, "optional operator* called for disengaged value"); 500 return this->__val_; 501 } 502 503 _LIBCPP_INLINE_VISIBILITY 504 constexpr explicit operator bool() const noexcept {return this->__engaged_;} 505 506 _LIBCPP_INLINE_VISIBILITY 507 constexpr value_type const& value() const 508 { 509 if (!this->__engaged_) 510 throw bad_optional_access("optional<T>::value: not engaged"); 511 return this->__val_; 512 } 513 514 _LIBCPP_INLINE_VISIBILITY 515 value_type& value() 516 { 517 if (!this->__engaged_) 518 throw bad_optional_access("optional<T>::value: not engaged"); 519 return this->__val_; 520 } 521 522 template <class _Up> 523 _LIBCPP_INLINE_VISIBILITY 524 constexpr value_type value_or(_Up&& __v) const& 525 { 526 static_assert(is_copy_constructible<value_type>::value, 527 "optional<T>::value_or: T must be copy constructible"); 528 static_assert(is_convertible<_Up, value_type>::value, 529 "optional<T>::value_or: U must be convertible to T"); 530 return this->__engaged_ ? this->__val_ : 531 static_cast<value_type>(_VSTD::forward<_Up>(__v)); 532 } 533 534 template <class _Up> 535 _LIBCPP_INLINE_VISIBILITY 536 value_type value_or(_Up&& __v) && 537 { 538 static_assert(is_move_constructible<value_type>::value, 539 "optional<T>::value_or: T must be move constructible"); 540 static_assert(is_convertible<_Up, value_type>::value, 541 "optional<T>::value_or: U must be convertible to T"); 542 return this->__engaged_ ? _VSTD::move(this->__val_) : 543 static_cast<value_type>(_VSTD::forward<_Up>(__v)); 544 } 545 546 private: 547 _LIBCPP_INLINE_VISIBILITY 548 value_type const* 549 __operator_arrow(true_type) const 550 { 551 return _VSTD::addressof(this->__val_); 552 } 553 554 _LIBCPP_INLINE_VISIBILITY 555 constexpr 556 value_type const* 557 __operator_arrow(false_type) const 558 { 559 return &this->__val_; 560 } 561 }; 562 563 template <class _Tp> 564 inline _LIBCPP_INLINE_VISIBILITY 565 constexpr 566 bool 567 operator==(const optional<_Tp>& __x, const optional<_Tp>& __y) 568 { 569 if (static_cast<bool>(__x) != static_cast<bool>(__y)) 570 return false; 571 if (!static_cast<bool>(__x)) 572 return true; 573 return *__x == *__y; 574 } 575 576 template <class _Tp> 577 inline _LIBCPP_INLINE_VISIBILITY 578 constexpr 579 bool 580 operator<(const optional<_Tp>& __x, const optional<_Tp>& __y) 581 { 582 if (!static_cast<bool>(__y)) 583 return false; 584 if (!static_cast<bool>(__x)) 585 return true; 586 return less<_Tp>{}(*__x, *__y); 587 } 588 589 template <class _Tp> 590 inline _LIBCPP_INLINE_VISIBILITY 591 constexpr 592 bool 593 operator==(const optional<_Tp>& __x, nullopt_t) noexcept 594 { 595 return !static_cast<bool>(__x); 596 } 597 598 template <class _Tp> 599 inline _LIBCPP_INLINE_VISIBILITY 600 constexpr 601 bool 602 operator==(nullopt_t, const optional<_Tp>& __x) noexcept 603 { 604 return !static_cast<bool>(__x); 605 } 606 607 template <class _Tp> 608 inline _LIBCPP_INLINE_VISIBILITY 609 constexpr 610 bool 611 operator<(const optional<_Tp>&, nullopt_t) noexcept 612 { 613 return false; 614 } 615 616 template <class _Tp> 617 inline _LIBCPP_INLINE_VISIBILITY 618 constexpr 619 bool 620 operator<(nullopt_t, const optional<_Tp>& __x) noexcept 621 { 622 return static_cast<bool>(__x); 623 } 624 625 template <class _Tp> 626 inline _LIBCPP_INLINE_VISIBILITY 627 constexpr 628 bool 629 operator==(const optional<_Tp>& __x, const _Tp& __v) 630 { 631 return static_cast<bool>(__x) ? *__x == __v : false; 632 } 633 634 template <class _Tp> 635 inline _LIBCPP_INLINE_VISIBILITY 636 constexpr 637 bool 638 operator==(const _Tp& __v, const optional<_Tp>& __x) 639 { 640 return static_cast<bool>(__x) ? *__x == __v : false; 641 } 642 643 template <class _Tp> 644 inline _LIBCPP_INLINE_VISIBILITY 645 constexpr 646 bool 647 operator<(const optional<_Tp>& __x, const _Tp& __v) 648 { 649 return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true; 650 } 651 652 template <class _Tp> 653 inline _LIBCPP_INLINE_VISIBILITY 654 constexpr 655 bool 656 operator<(const _Tp& __v, const optional<_Tp>& __x) 657 { 658 return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false; 659 } 660 661 template <class _Tp> 662 inline _LIBCPP_INLINE_VISIBILITY 663 void 664 swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 665 { 666 __x.swap(__y); 667 } 668 669 template <class _Tp> 670 inline _LIBCPP_INLINE_VISIBILITY 671 constexpr 672 optional<typename decay<_Tp>::type> 673 make_optional(_Tp&& __v) 674 { 675 return optional<typename decay<_Tp>::type>(_VSTD::forward<_Tp>(__v)); 676 } 677 678 }}} // namespace std::experimental::__library_fundamentals_v1 679 680 _LIBCPP_BEGIN_NAMESPACE_STD 681 682 template <class _Tp> 683 struct _LIBCPP_TYPE_VIS_ONLY hash<std::experimental::optional<_Tp> > 684 { 685 typedef std::experimental::optional<_Tp> argument_type; 686 typedef size_t result_type; 687 688 _LIBCPP_INLINE_VISIBILITY 689 result_type operator()(const argument_type& __opt) const _NOEXCEPT 690 { 691 return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0; 692 } 693 }; 694 695 _LIBCPP_END_NAMESPACE_STD 696 697 #endif // _LIBCPP_STD_VER > 11 698 699 #endif // _LIBCPP_ARRAY 700