1// Copyright (C) 2011 - 2012 Andrzej Krzemienski. 2// 3// Use, modification, and distribution is subject to the Boost Software 4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 5// http://www.boost.org/LICENSE_1_0.txt) 6// 7// The idea and interface is based on Boost.Optional library 8// authored by Fernando Luis Cacciola Carballal 9 10# ifndef ___OPTIONAL_HPP___ 11# define ___OPTIONAL_HPP___ 12 13# include <utility> 14# include <type_traits> 15# include <initializer_list> 16# include <cassert> 17# include <functional> 18# include <string> 19# include <stdexcept> 20 21# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false 22 23# if defined __GNUC__ // NOTE: GNUC is also defined for Clang 24# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) 25# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 26# elif (__GNUC__ > 4) 27# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 28# endif 29# 30# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) 31# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 32# elif (__GNUC__ > 4) 33# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 34# endif 35# 36# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) 37# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 38# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) 39# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 40# elif (__GNUC__ > 4) 41# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 42# endif 43# endif 44# 45# if defined __clang_major__ 46# if (__clang_major__ == 3 && __clang_minor__ >= 5) 47# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 48# elif (__clang_major__ > 3) 49# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 50# endif 51# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 52# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 53# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) 54# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 55# endif 56# endif 57# 58# if defined _MSC_VER 59# if (_MSC_VER >= 1900) 60# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 61# endif 62# endif 63 64# if defined __clang__ 65# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) 66# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 67# else 68# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 69# endif 70# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 71# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 72# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 73# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 74# else 75# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 76# endif 77 78 79# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 80# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 81# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr 82# else 83# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 84# define OPTIONAL_CONSTEXPR_INIT_LIST 85# endif 86 87# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) 88# define OPTIONAL_HAS_MOVE_ACCESSORS 1 89# else 90# define OPTIONAL_HAS_MOVE_ACCESSORS 0 91# endif 92 93# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr 94# if (defined __cplusplus) && (__cplusplus == 201103L) 95# define OPTIONAL_MUTABLE_CONSTEXPR 96# else 97# define OPTIONAL_MUTABLE_CONSTEXPR constexpr 98# endif 99 100namespace std{ 101 102namespace experimental{ 103 104// BEGIN workaround for missing is_trivially_destructible 105# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 106 // leave it: it is already there 107# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 108 // leave it: it is already there 109# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 110 // leave it: it is already there 111# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 112 // leave it: the user doesn't want it 113# else 114 template <typename T> 115 using is_trivially_destructible = std::has_trivial_destructor<T>; 116# endif 117// END workaround for missing is_trivially_destructible 118 119# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) 120 // leave it; our metafunctions are already defined. 121# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 122 // leave it; our metafunctions are already defined. 123# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 124 // leave it: it is already there 125# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 126 // leave it: the user doesn't want it 127# else 128 129 130// workaround for missing traits in GCC and CLANG 131template <class T> 132struct is_nothrow_move_constructible 133{ 134 constexpr static bool value = std::is_nothrow_constructible<T, T&&>::value; 135}; 136 137 138template <class T, class U> 139struct is_assignable 140{ 141 template <class X, class Y> 142 constexpr static bool has_assign(...) { return false; } 143 144 template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) > 145 // the comma operator is necessary for the cases where operator= returns void 146 constexpr static bool has_assign(bool) { return true; } 147 148 constexpr static bool value = has_assign<T, U>(true); 149}; 150 151 152template <class T> 153struct is_nothrow_move_assignable 154{ 155 template <class X, bool has_any_move_assign> 156 struct has_nothrow_move_assign { 157 constexpr static bool value = false; 158 }; 159 160 template <class X> 161 struct has_nothrow_move_assign<X, true> { 162 constexpr static bool value = noexcept( std::declval<X&>() = std::declval<X&&>() ); 163 }; 164 165 constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; 166}; 167// end workaround 168 169 170# endif 171 172 173 174// 20.5.4, optional for object types 175template <class T> class optional; 176 177// 20.5.5, optional for lvalue reference types 178template <class T> class optional<T&>; 179 180 181// workaround: std utility functions aren't constexpr yet 182template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type& t) noexcept 183{ 184 return static_cast<T&&>(t); 185} 186 187template <class T> inline constexpr T&& constexpr_forward(typename std::remove_reference<T>::type&& t) noexcept 188{ 189 static_assert(!std::is_lvalue_reference<T>::value, "!!"); 190 return static_cast<T&&>(t); 191} 192 193template <class T> inline constexpr typename std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept 194{ 195 return static_cast<typename std::remove_reference<T>::type&&>(t); 196} 197 198 199#if defined NDEBUG 200# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) 201#else 202# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) 203#endif 204 205 206namespace detail_ 207{ 208 209// static_addressof: a constexpr version of addressof 210template <typename T> 211struct has_overloaded_addressof 212{ 213 template <class X> 214 constexpr static bool has_overload(...) { return false; } 215 216 template <class X, size_t S = sizeof(std::declval<X&>().operator&()) > 217 constexpr static bool has_overload(bool) { return true; } 218 219 constexpr static bool value = has_overload<T>(true); 220}; 221 222template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> 223constexpr T* static_addressof(T& ref) 224{ 225 return &ref; 226} 227 228template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> 229T* static_addressof(T& ref) 230{ 231 return std::addressof(ref); 232} 233 234 235// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A 236template <class U> 237constexpr U convert(U v) { return v; } 238 239} // namespace detail 240 241 242constexpr struct trivial_init_t{} trivial_init{}; 243 244 245// 20.5.6, In-place construction 246constexpr struct in_place_t{} in_place{}; 247 248 249// 20.5.7, Disengaged state indicator 250struct nullopt_t 251{ 252 struct init{}; 253 constexpr explicit nullopt_t(init){} 254}; 255constexpr nullopt_t nullopt{nullopt_t::init()}; 256 257 258// 20.5.8, class bad_optional_access 259class bad_optional_access : public logic_error { 260public: 261 explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} 262 explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} 263}; 264 265 266template <class T> 267union storage_t 268{ 269 unsigned char dummy_; 270 T value_; 271 272 constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; 273 274 template <class... Args> 275 constexpr storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {} 276 277 ~storage_t(){} 278}; 279 280 281template <class T> 282union constexpr_storage_t 283{ 284 unsigned char dummy_; 285 T value_; 286 287 constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; 288 289 template <class... Args> 290 constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward<Args>(args)...) {} 291 292 ~constexpr_storage_t() = default; 293}; 294 295 296template <class T> 297struct optional_base 298{ 299 bool init_; 300 storage_t<T> storage_; 301 302 constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; 303 304 explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} 305 306 explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} 307 308 template <class... Args> explicit optional_base(in_place_t, Args&&... args) 309 : init_(true), storage_(constexpr_forward<Args>(args)...) {} 310 311 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> 312 explicit optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) 313 : init_(true), storage_(il, std::forward<Args>(args)...) {} 314 315 ~optional_base() { if (init_) storage_.value_.T::~T(); } 316}; 317 318 319template <class T> 320struct constexpr_optional_base 321{ 322 bool init_; 323 constexpr_storage_t<T> storage_; 324 325 constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; 326 327 explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} 328 329 explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} 330 331 template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) 332 : init_(true), storage_(constexpr_forward<Args>(args)...) {} 333 334 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> 335 OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list<U> il, Args&&... args) 336 : init_(true), storage_(il, std::forward<Args>(args)...) {} 337 338 ~constexpr_optional_base() = default; 339}; 340 341template <class T> 342using OptionalBase = typename std::conditional< 343 is_trivially_destructible<T>::value, // if possible 344 constexpr_optional_base<typename std::remove_const<T>::type>, // use base with trivial destructor 345 optional_base<typename std::remove_const<T>::type> 346>::type; 347 348 349 350template <class T> 351class optional : private OptionalBase<T> 352{ 353 static_assert( !std::is_same<typename std::decay<T>::type, nullopt_t>::value, "bad T" ); 354 static_assert( !std::is_same<typename std::decay<T>::type, in_place_t>::value, "bad T" ); 355 356 357 constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; } 358 typename std::remove_const<T>::type* dataptr() { return std::addressof(OptionalBase<T>::storage_.value_); } 359 constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage_.value_); } 360 361# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 362 constexpr const T& contained_val() const& { return OptionalBase<T>::storage_.value_; } 363# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 364 OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); } 365 OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage_.value_; } 366# else 367 T& contained_val() & { return OptionalBase<T>::storage_.value_; } 368 T&& contained_val() && { return std::move(OptionalBase<T>::storage_.value_); } 369# endif 370# else 371 constexpr const T& contained_val() const { return OptionalBase<T>::storage_.value_; } 372 T& contained_val() { return OptionalBase<T>::storage_.value_; } 373# endif 374 375 void clear() noexcept { 376 if (initialized()) dataptr()->T::~T(); 377 OptionalBase<T>::init_ = false; 378 } 379 380 template <class... Args> 381 void initialize(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...))) 382 { 383 assert(!OptionalBase<T>::init_); 384 ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...); 385 OptionalBase<T>::init_ = true; 386 } 387 388 template <class U, class... Args> 389 void initialize(std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, std::forward<Args>(args)...))) 390 { 391 assert(!OptionalBase<T>::init_); 392 ::new (static_cast<void*>(dataptr())) T(il, std::forward<Args>(args)...); 393 OptionalBase<T>::init_ = true; 394 } 395 396public: 397 typedef T value_type; 398 399 // 20.5.5.1, constructors 400 constexpr optional() noexcept : OptionalBase<T>() {}; 401 constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {}; 402 403 optional(const optional& rhs) 404 : OptionalBase<T>() 405 { 406 if (rhs.initialized()) { 407 ::new (static_cast<void*>(dataptr())) T(*rhs); 408 OptionalBase<T>::init_ = true; 409 } 410 } 411 412 optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value) 413 : OptionalBase<T>() 414 { 415 if (rhs.initialized()) { 416 ::new (static_cast<void*>(dataptr())) T(std::move(*rhs)); 417 OptionalBase<T>::init_ = true; 418 } 419 } 420 421 constexpr optional(const T& v) : OptionalBase<T>(v) {} 422 423 constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {} 424 425 template <class... Args> 426 explicit constexpr optional(in_place_t, Args&&... args) 427 : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {} 428 429 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(is_constructible<T, std::initializer_list<U>>)> 430 OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args) 431 : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {} 432 433 // 20.5.4.2, Destructor 434 ~optional() = default; 435 436 // 20.5.4.3, assignment 437 optional& operator=(nullopt_t) noexcept 438 { 439 clear(); 440 return *this; 441 } 442 443 optional& operator=(const optional& rhs) 444 { 445 if (initialized() == true && rhs.initialized() == false) clear(); 446 else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); 447 else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; 448 return *this; 449 } 450 451 optional& operator=(optional&& rhs) 452 noexcept(is_nothrow_move_assignable<T>::value && is_nothrow_move_constructible<T>::value) 453 { 454 if (initialized() == true && rhs.initialized() == false) clear(); 455 else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); 456 else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); 457 return *this; 458 } 459 460 template <class U> 461 auto operator=(U&& v) 462 -> typename enable_if 463 < 464 is_same<typename decay<U>::type, T>::value, 465 optional& 466 >::type 467 { 468 if (initialized()) { contained_val() = std::forward<U>(v); } 469 else { initialize(std::forward<U>(v)); } 470 return *this; 471 } 472 473 474 template <class... Args> 475 void emplace(Args&&... args) 476 { 477 clear(); 478 initialize(std::forward<Args>(args)...); 479 } 480 481 template <class U, class... Args> 482 void emplace(initializer_list<U> il, Args&&... args) 483 { 484 clear(); 485 initialize<U, Args...>(il, std::forward<Args>(args)...); 486 } 487 488 // 20.5.4.4, Swap 489 void swap(optional<T>& rhs) noexcept(is_nothrow_move_constructible<T>::value && noexcept(swap(declval<T&>(), declval<T&>()))) 490 { 491 if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } 492 else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } 493 else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } 494 } 495 496 // 20.5.4.5, Observers 497 498 explicit constexpr operator bool() const noexcept { return initialized(); } 499 constexpr bool has_value() const noexcept { return initialized(); } 500 501 constexpr T const* operator ->() const { 502 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); 503 } 504 505# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 506 507 OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { 508 assert (initialized()); 509 return dataptr(); 510 } 511 512 constexpr T const& operator *() const& { 513 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); 514 } 515 516 OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { 517 assert (initialized()); 518 return contained_val(); 519 } 520 521 OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { 522 assert (initialized()); 523 return constexpr_move(contained_val()); 524 } 525 526 constexpr T const& value() const& { 527 return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); 528 } 529 530 OPTIONAL_MUTABLE_CONSTEXPR T& value() & { 531 return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); 532 } 533 534 OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { 535 if (!initialized()) throw bad_optional_access("bad optional access"); 536 return std::move(contained_val()); 537 } 538 539# else 540 541 T* operator ->() { 542 assert (initialized()); 543 return dataptr(); 544 } 545 546 constexpr T const& operator *() const { 547 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); 548 } 549 550 T& operator *() { 551 assert (initialized()); 552 return contained_val(); 553 } 554 555 constexpr T const& value() const { 556 return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); 557 } 558 559 T& value() { 560 return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); 561 } 562 563# endif 564 565# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 566 567 template <class V> 568 constexpr T value_or(V&& v) const& 569 { 570 return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); 571 } 572 573# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 574 575 template <class V> 576 OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && 577 { 578 return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); 579 } 580 581# else 582 583 template <class V> 584 T value_or(V&& v) && 585 { 586 return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); 587 } 588 589# endif 590 591# else 592 593 template <class V> 594 constexpr T value_or(V&& v) const 595 { 596 return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); 597 } 598 599# endif 600 601 // 20.6.3.6, modifiers 602 void reset() noexcept { clear(); } 603}; 604 605 606template <class T> 607class optional<T&> 608{ 609 static_assert( !std::is_same<T, nullopt_t>::value, "bad T" ); 610 static_assert( !std::is_same<T, in_place_t>::value, "bad T" ); 611 T* ref; 612 613public: 614 615 // 20.5.5.1, construction/destruction 616 constexpr optional() noexcept : ref(nullptr) {} 617 618 constexpr optional(nullopt_t) noexcept : ref(nullptr) {} 619 620 constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} 621 622 optional(T&&) = delete; 623 624 constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} 625 626 explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} 627 628 explicit optional(in_place_t, T&&) = delete; 629 630 ~optional() = default; 631 632 // 20.5.5.2, mutation 633 optional& operator=(nullopt_t) noexcept { 634 ref = nullptr; 635 return *this; 636 } 637 638 // optional& operator=(const optional& rhs) noexcept { 639 // ref = rhs.ref; 640 // return *this; 641 // } 642 643 // optional& operator=(optional&& rhs) noexcept { 644 // ref = rhs.ref; 645 // return *this; 646 // } 647 648 template <typename U> 649 auto operator=(U&& rhs) noexcept 650 -> typename enable_if 651 < 652 is_same<typename decay<U>::type, optional<T&>>::value, 653 optional& 654 >::type 655 { 656 ref = rhs.ref; 657 return *this; 658 } 659 660 template <typename U> 661 auto operator=(U&& rhs) noexcept 662 -> typename enable_if 663 < 664 !is_same<typename decay<U>::type, optional<T&>>::value, 665 optional& 666 >::type 667 = delete; 668 669 void emplace(T& v) noexcept { 670 ref = detail_::static_addressof(v); 671 } 672 673 void emplace(T&&) = delete; 674 675 676 void swap(optional<T&>& rhs) noexcept 677 { 678 std::swap(ref, rhs.ref); 679 } 680 681 // 20.5.5.3, observers 682 constexpr T* operator->() const { 683 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); 684 } 685 686 constexpr T& operator*() const { 687 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); 688 } 689 690 constexpr T& value() const { 691 return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); 692 } 693 694 explicit constexpr operator bool() const noexcept { 695 return ref != nullptr; 696 } 697 698 constexpr bool has_value() const noexcept { 699 return ref != nullptr; 700 } 701 702 template <class V> 703 constexpr typename decay<T>::type value_or(V&& v) const 704 { 705 return *this ? **this : detail_::convert<typename decay<T>::type>(constexpr_forward<V>(v)); 706 } 707 708 // x.x.x.x, modifiers 709 void reset() noexcept { ref = nullptr; } 710}; 711 712 713template <class T> 714class optional<T&&> 715{ 716 static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); 717}; 718 719 720// 20.5.8, Relational operators 721template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y) 722{ 723 return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; 724} 725 726template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y) 727{ 728 return !(x == y); 729} 730 731template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y) 732{ 733 return (!y) ? false : (!x) ? true : *x < *y; 734} 735 736template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y) 737{ 738 return (y < x); 739} 740 741template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y) 742{ 743 return !(y < x); 744} 745 746template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y) 747{ 748 return !(x < y); 749} 750 751 752// 20.5.9, Comparison with nullopt 753template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept 754{ 755 return (!x); 756} 757 758template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept 759{ 760 return (!x); 761} 762 763template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept 764{ 765 return bool(x); 766} 767 768template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept 769{ 770 return bool(x); 771} 772 773template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept 774{ 775 return false; 776} 777 778template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept 779{ 780 return bool(x); 781} 782 783template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept 784{ 785 return (!x); 786} 787 788template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept 789{ 790 return true; 791} 792 793template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept 794{ 795 return bool(x); 796} 797 798template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept 799{ 800 return false; 801} 802 803template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept 804{ 805 return true; 806} 807 808template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept 809{ 810 return (!x); 811} 812 813 814 815// 20.5.10, Comparison with T 816template <class T> constexpr bool operator==(const optional<T>& x, const T& v) 817{ 818 return bool(x) ? *x == v : false; 819} 820 821template <class T> constexpr bool operator==(const T& v, const optional<T>& x) 822{ 823 return bool(x) ? v == *x : false; 824} 825 826template <class T> constexpr bool operator!=(const optional<T>& x, const T& v) 827{ 828 return bool(x) ? *x != v : true; 829} 830 831template <class T> constexpr bool operator!=(const T& v, const optional<T>& x) 832{ 833 return bool(x) ? v != *x : true; 834} 835 836template <class T> constexpr bool operator<(const optional<T>& x, const T& v) 837{ 838 return bool(x) ? *x < v : true; 839} 840 841template <class T> constexpr bool operator>(const T& v, const optional<T>& x) 842{ 843 return bool(x) ? v > *x : true; 844} 845 846template <class T> constexpr bool operator>(const optional<T>& x, const T& v) 847{ 848 return bool(x) ? *x > v : false; 849} 850 851template <class T> constexpr bool operator<(const T& v, const optional<T>& x) 852{ 853 return bool(x) ? v < *x : false; 854} 855 856template <class T> constexpr bool operator>=(const optional<T>& x, const T& v) 857{ 858 return bool(x) ? *x >= v : false; 859} 860 861template <class T> constexpr bool operator<=(const T& v, const optional<T>& x) 862{ 863 return bool(x) ? v <= *x : false; 864} 865 866template <class T> constexpr bool operator<=(const optional<T>& x, const T& v) 867{ 868 return bool(x) ? *x <= v : true; 869} 870 871template <class T> constexpr bool operator>=(const T& v, const optional<T>& x) 872{ 873 return bool(x) ? v >= *x : true; 874} 875 876 877// Comparison of optional<T&> with T 878template <class T> constexpr bool operator==(const optional<T&>& x, const T& v) 879{ 880 return bool(x) ? *x == v : false; 881} 882 883template <class T> constexpr bool operator==(const T& v, const optional<T&>& x) 884{ 885 return bool(x) ? v == *x : false; 886} 887 888template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v) 889{ 890 return bool(x) ? *x != v : true; 891} 892 893template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x) 894{ 895 return bool(x) ? v != *x : true; 896} 897 898template <class T> constexpr bool operator<(const optional<T&>& x, const T& v) 899{ 900 return bool(x) ? *x < v : true; 901} 902 903template <class T> constexpr bool operator>(const T& v, const optional<T&>& x) 904{ 905 return bool(x) ? v > *x : true; 906} 907 908template <class T> constexpr bool operator>(const optional<T&>& x, const T& v) 909{ 910 return bool(x) ? *x > v : false; 911} 912 913template <class T> constexpr bool operator<(const T& v, const optional<T&>& x) 914{ 915 return bool(x) ? v < *x : false; 916} 917 918template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v) 919{ 920 return bool(x) ? *x >= v : false; 921} 922 923template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x) 924{ 925 return bool(x) ? v <= *x : false; 926} 927 928template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v) 929{ 930 return bool(x) ? *x <= v : true; 931} 932 933template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x) 934{ 935 return bool(x) ? v >= *x : true; 936} 937 938// Comparison of optional<T const&> with T 939template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v) 940{ 941 return bool(x) ? *x == v : false; 942} 943 944template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x) 945{ 946 return bool(x) ? v == *x : false; 947} 948 949template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v) 950{ 951 return bool(x) ? *x != v : true; 952} 953 954template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x) 955{ 956 return bool(x) ? v != *x : true; 957} 958 959template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v) 960{ 961 return bool(x) ? *x < v : true; 962} 963 964template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x) 965{ 966 return bool(x) ? v > *x : true; 967} 968 969template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v) 970{ 971 return bool(x) ? *x > v : false; 972} 973 974template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x) 975{ 976 return bool(x) ? v < *x : false; 977} 978 979template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v) 980{ 981 return bool(x) ? *x >= v : false; 982} 983 984template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x) 985{ 986 return bool(x) ? v <= *x : false; 987} 988 989template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v) 990{ 991 return bool(x) ? *x <= v : true; 992} 993 994template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x) 995{ 996 return bool(x) ? v >= *x : true; 997} 998 999 1000// 20.5.12, Specialized algorithms 1001template <class T> 1002void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) 1003{ 1004 x.swap(y); 1005} 1006 1007 1008template <class T> 1009constexpr optional<typename decay<T>::type> make_optional(T&& v) 1010{ 1011 return optional<typename decay<T>::type>(constexpr_forward<T>(v)); 1012} 1013 1014template <class X> 1015constexpr optional<X&> make_optional(reference_wrapper<X> v) 1016{ 1017 return optional<X&>(v.get()); 1018} 1019 1020 1021} // namespace experimental 1022} // namespace std 1023 1024namespace std 1025{ 1026 template <typename T> 1027 struct hash<std::experimental::optional<T>> 1028 { 1029 typedef typename hash<T>::result_type result_type; 1030 typedef std::experimental::optional<T> argument_type; 1031 1032 constexpr result_type operator()(argument_type const& arg) const { 1033 return arg ? std::hash<T>{}(*arg) : result_type{}; 1034 } 1035 }; 1036 1037 template <typename T> 1038 struct hash<std::experimental::optional<T&>> 1039 { 1040 typedef typename hash<T>::result_type result_type; 1041 typedef std::experimental::optional<T&> argument_type; 1042 1043 constexpr result_type operator()(argument_type const& arg) const { 1044 return arg ? std::hash<T>{}(*arg) : result_type{}; 1045 } 1046 }; 1047} 1048 1049# undef TR2_OPTIONAL_REQUIRES 1050# undef TR2_OPTIONAL_ASSERTED_EXPRESSION 1051 1052# endif //___OPTIONAL_HPP___ 1053