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