optional revision 261272
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 { namespace experimental { 22 23// optional for object types 24template <class T> 25class optional 26{ 27public: 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 72struct in_place_t{}; 73constexpr in_place_t in_place{}; 74 75// Disengaged state indicator 76struct nullopt_t{see below}; 77constexpr nullopt_t nullopt(unspecified); 78 79// class bad_optional_access 80class bad_optional_access 81 : public logic_error 82{ 83public: 84 explicit bad_optional_access(const string& what_arg); 85 explicit bad_optional_access(const char* what_arg); 86}; 87 88// Relational operators 89template <class T> constexpr bool operator==(const optional<T>&, const optional<T>&); 90template <class T> constexpr bool operator< (const optional<T>&, const optional<T>&); 91 92// Comparison with nullopt 93template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; 94template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; 95template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; 96template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; 97 98// Comparison with T 99template <class T> constexpr bool operator==(const optional<T>&, const T&); 100template <class T> constexpr bool operator==(const T&, const optional<T>&); 101template <class T> constexpr bool operator<(const optional<T>&, const T&); 102template <class T> constexpr bool operator<(const T&, const optional<T>&); 103 104// Specialized algorithms 105template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below); 106template <class T> constexpr optional<typename decay<T>::type> make_optional(T&&); 107 108// hash support 109template <class T> struct hash; 110template <class T> struct hash<optional<T>>; 111 112}} // std::experimental 113 114*/ 115 116#include <__config> 117#include <functional> 118#include <stdexcept> 119 120namespace std { namespace experimental { 121 122class _LIBCPP_EXCEPTION_ABI bad_optional_access 123 : public logic_error 124{ 125public: 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 134private: 135 bad_optional_access(const bad_optional_access&); 136 bad_optional_access& operator=(const bad_optional_access&); 137public: 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 164namespace std { namespace experimental { inline namespace __library_fundamentals_v1 { 165 166struct in_place_t {}; 167constexpr in_place_t in_place{}; 168 169struct nullopt_t 170{ 171 explicit constexpr nullopt_t(int) noexcept {} 172}; 173 174constexpr nullopt_t nullopt{0}; 175 176template <class _Tp, bool = is_trivially_destructible<_Tp>::value> 177class __optional_storage 178{ 179protected: 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 234template <class _Tp> 235class __optional_storage<_Tp, true> 236{ 237protected: 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 285template <class _Tp> 286class optional 287 : private __optional_storage<_Tp> 288{ 289 typedef __optional_storage<_Tp> __base; 290public: 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 546private: 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 563template <class _Tp> 564inline _LIBCPP_INLINE_VISIBILITY 565constexpr 566bool 567operator==(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 576template <class _Tp> 577inline _LIBCPP_INLINE_VISIBILITY 578constexpr 579bool 580operator<(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 589template <class _Tp> 590inline _LIBCPP_INLINE_VISIBILITY 591constexpr 592bool 593operator==(const optional<_Tp>& __x, nullopt_t) noexcept 594{ 595 return !static_cast<bool>(__x); 596} 597 598template <class _Tp> 599inline _LIBCPP_INLINE_VISIBILITY 600constexpr 601bool 602operator==(nullopt_t, const optional<_Tp>& __x) noexcept 603{ 604 return !static_cast<bool>(__x); 605} 606 607template <class _Tp> 608inline _LIBCPP_INLINE_VISIBILITY 609constexpr 610bool 611operator<(const optional<_Tp>&, nullopt_t) noexcept 612{ 613 return false; 614} 615 616template <class _Tp> 617inline _LIBCPP_INLINE_VISIBILITY 618constexpr 619bool 620operator<(nullopt_t, const optional<_Tp>& __x) noexcept 621{ 622 return static_cast<bool>(__x); 623} 624 625template <class _Tp> 626inline _LIBCPP_INLINE_VISIBILITY 627constexpr 628bool 629operator==(const optional<_Tp>& __x, const _Tp& __v) 630{ 631 return static_cast<bool>(__x) ? *__x == __v : false; 632} 633 634template <class _Tp> 635inline _LIBCPP_INLINE_VISIBILITY 636constexpr 637bool 638operator==(const _Tp& __v, const optional<_Tp>& __x) 639{ 640 return static_cast<bool>(__x) ? *__x == __v : false; 641} 642 643template <class _Tp> 644inline _LIBCPP_INLINE_VISIBILITY 645constexpr 646bool 647operator<(const optional<_Tp>& __x, const _Tp& __v) 648{ 649 return static_cast<bool>(__x) ? less<_Tp>{}(*__x, __v) : true; 650} 651 652template <class _Tp> 653inline _LIBCPP_INLINE_VISIBILITY 654constexpr 655bool 656operator<(const _Tp& __v, const optional<_Tp>& __x) 657{ 658 return static_cast<bool>(__x) ? less<_Tp>{}(__v, *__x) : false; 659} 660 661template <class _Tp> 662inline _LIBCPP_INLINE_VISIBILITY 663void 664swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y))) 665{ 666 __x.swap(__y); 667} 668 669template <class _Tp> 670inline _LIBCPP_INLINE_VISIBILITY 671constexpr 672optional<typename decay<_Tp>::type> 673make_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 682template <class _Tp> 683struct _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