1 // sol2 2 3 // The MIT License (MIT) 4 5 // Copyright (c) 2013-2018 Rapptz, ThePhD and contributors 6 7 // Permission is hereby granted, free of charge, to any person obtaining a copy of 8 // this software and associated documentation files (the "Software"), to deal in 9 // the Software without restriction, including without limitation the rights to 10 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 // the Software, and to permit persons to whom the Software is furnished to do so, 12 // subject to the following conditions: 13 14 // The above copyright notice and this permission notice shall be included in all 15 // copies or substantial portions of the Software. 16 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24 // Copyright (C) 2011 - 2012 Andrzej Krzemienski. 25 // Use, modification, and distribution is subject to the Boost Software 26 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 27 // http://www.boost.org/LICENSE_1_0.txt) 28 // 29 // The idea and interface is based on Boost.Optional library 30 // authored by Fernando Luis Cacciola Carballal 31 32 #ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP 33 #define SOL_OPTIONAL_IMPLEMENTATION_HPP 34 35 #include "in_place.hpp" 36 37 #include <utility> 38 #include <type_traits> 39 #include <initializer_list> 40 #include <cassert> 41 #include <functional> 42 #include <string> 43 #include <stdexcept> 44 #if defined(SOL_NO_EXCEPTIONS) && SOL_NO_EXCEPTIONS 45 #include <cstdlib> 46 #endif // Exceptions 47 48 #define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false 49 50 #if defined __GNUC__ // NOTE: GNUC is also defined for Clang 51 #if (__GNUC__ >= 5) 52 #define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ 53 #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 54 #elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) 55 #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 56 #elif (__GNUC__ > 4) 57 #define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 58 #endif 59 # 60 #if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) 61 #define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 62 #elif (__GNUC__ > 4) 63 #define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ 64 #endif 65 # 66 #if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) 67 #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 68 #elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) 69 #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 70 #elif (__GNUC__ > 4) 71 #define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 72 #endif 73 #endif 74 # 75 #if defined __clang_major__ 76 #if (__clang_major__ == 3 && __clang_minor__ >= 5) 77 #define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 78 #elif (__clang_major__ > 3) 79 #define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 80 #endif 81 #if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ 82 #define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 83 #elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) 84 #define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 85 #endif 86 #endif 87 # 88 #if defined _MSC_VER 89 #if (_MSC_VER >= 1900) 90 #define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 91 #endif 92 #endif 93 94 #if defined __clang__ 95 #if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) 96 #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 97 #else 98 #define OPTIONAL_HAS_THIS_RVALUE_REFS 0 99 #endif 100 #elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 101 #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 102 #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 103 #define OPTIONAL_HAS_THIS_RVALUE_REFS 1 104 #else 105 #define OPTIONAL_HAS_THIS_RVALUE_REFS 0 106 #endif 107 108 #if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ 109 #define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 110 #define OPTIONAL_CONSTEXPR_INIT_LIST constexpr 111 #else 112 #define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 113 #define OPTIONAL_CONSTEXPR_INIT_LIST 114 #endif 115 116 #if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)) 117 #define OPTIONAL_HAS_MOVE_ACCESSORS 1 118 #else 119 #define OPTIONAL_HAS_MOVE_ACCESSORS 0 120 #endif 121 122 #// In C++11 constexpr implies const, so we need to make non-const members also non-constexpr 123 #if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L)) 124 #define OPTIONAL_MUTABLE_CONSTEXPR 125 #else 126 #define OPTIONAL_MUTABLE_CONSTEXPR constexpr 127 #endif 128 129 #if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 130 #pragma warning(push) 131 #pragma warning(disable : 4814) 132 #endif 133 134 namespace sol { 135 136 // BEGIN workaround for missing is_trivially_destructible 137 #if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ 138 // leave it: it is already there 139 #elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 140 // leave it: it is already there 141 #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 142 // leave it: it is already there 143 #elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 144 // leave it: the user doesn't want it 145 #else 146 template <typename T> 147 using is_trivially_destructible = ::std::has_trivial_destructor<T>; 148 #endif 149 // END workaround for missing is_trivially_destructible 150 151 #if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) 152 // leave it; our metafunctions are already defined. 153 #elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ 154 // leave it; our metafunctions are already defined. 155 #elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 156 // leave it: it is already there 157 #elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS 158 // leave it: the user doesn't want it 159 #else 160 161 // workaround for missing traits in GCC and CLANG 162 template <class T> 163 struct is_nothrow_move_constructible { 164 static constexprbool value = ::std::is_nothrow_constructible<T, T&&>::value; 165 }; 166 167 template <class T, class U> 168 struct is_assignable { 169 template <class X, class Y> 170 static constexprbool has_assign(...) { 171 return false; 172 } 173 174 template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true))> 175 // the comma operator is necessary for the cases where operator= returns void 176 static constexprbool has_assign(bool) { 177 return true; 178 } 179 180 static constexprbool value = has_assign<T, U>(true); 181 }; 182 183 template <class T> 184 struct is_nothrow_move_assignable { 185 template <class X, bool has_any_move_assign> 186 struct has_nothrow_move_assign { 187 static constexprbool value = false; 188 }; 189 190 template <class X> 191 struct has_nothrow_move_assign<X, true> { 192 static constexprbool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>()); 193 }; 194 195 static constexprbool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value; 196 }; 197 // end workaround 198 199 #endif 200 201 // 20.5.4, optional for object types 202 template <class T> 203 class optional; 204 205 // 20.5.5, optional for lvalue reference types 206 template <class T> 207 class optional<T&>; 208 209 // workaround: std utility functions aren't constexpr yet 210 template <class T> constexpr_forward(typename::std::remove_reference<T>::type & t)211 inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept { 212 return static_cast<T&&>(t); 213 } 214 215 template <class T> constexpr_forward(typename::std::remove_reference<T>::type && t)216 inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept { 217 static_assert(!::std::is_lvalue_reference<T>::value, "!!"); 218 return static_cast<T&&>(t); 219 } 220 221 template <class T> constexpr_move(T && t)222 inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept { 223 return static_cast<typename ::std::remove_reference<T>::type&&>(t); 224 } 225 226 #if defined NDEBUG 227 #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) 228 #else 229 #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR))) 230 #endif 231 232 namespace detail_ { 233 234 // static_addressof: a constexpr version of addressof 235 template <typename T> 236 struct has_overloaded_addressof { 237 template <class X> has_overloadsol::detail_::has_overloaded_addressof238 static constexpr bool has_overload(...) { 239 return false; 240 } 241 242 template <class X, size_t S = sizeof(::std::declval<X&>().operator&())> has_overloadsol::detail_::has_overloaded_addressof243 static constexpr bool has_overload(bool) { 244 return true; 245 } 246 247 static constexpr bool value = has_overload<T>(true); 248 }; 249 250 template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)> static_addressof(T & ref)251 constexpr T* static_addressof(T& ref) { 252 return &ref; 253 } 254 255 template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)> 256 T* static_addressof(T& ref) { 257 return ::std::addressof(ref); 258 } 259 260 // 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 261 template <class U> convert(U v)262 constexpr U convert(U v) { 263 return v; 264 } 265 266 } // namespace detail_ 267 268 constexpr struct trivial_init_t { 269 } trivial_init{}; 270 271 // 20.5.7, Disengaged state indicator 272 struct nullopt_t { 273 struct init {}; nullopt_tsol::nullopt_t274 constexpr explicit nullopt_t(init) { 275 } 276 }; 277 constexpr nullopt_t nullopt{nullopt_t::init()}; 278 279 // 20.5.8, class bad_optional_access 280 class bad_optional_access : public ::std::logic_error { 281 public: bad_optional_access(const::std::string & what_arg)282 explicit bad_optional_access(const ::std::string& what_arg) 283 : ::std::logic_error{what_arg} { 284 } bad_optional_access(const char * what_arg)285 explicit bad_optional_access(const char* what_arg) 286 : ::std::logic_error{what_arg} { 287 } 288 }; 289 290 template <class T> 291 struct alignas(T) optional_base { 292 char storage_[sizeof(T)]; 293 bool init_; 294 optional_basesol::optional_base295 constexpr optional_base() noexcept 296 : storage_(), init_(false){}; 297 optional_basesol::optional_base298 explicit optional_base(const T& v) 299 : storage_(), init_(true) { 300 new (&storage()) T(v); 301 } 302 optional_basesol::optional_base303 explicit optional_base(T&& v) 304 : storage_(), init_(true) { 305 new (&storage()) T(constexpr_move(v)); 306 } 307 308 template <class... Args> optional_basesol::optional_base309 explicit optional_base(in_place_t, Args&&... args) 310 : init_(true), storage_() { 311 new (&storage()) T(constexpr_forward<Args>(args)...); 312 } 313 314 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> optional_basesol::optional_base315 explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) 316 : init_(true), storage_() { 317 new (&storage()) T(il, constexpr_forward<Args>(args)...); 318 } 319 #if defined __GNUC__ 320 #pragma GCC diagnostic push 321 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 322 #endif storagesol::optional_base323 T& storage() { 324 return *reinterpret_cast<T*>(&storage_[0]); 325 } 326 storagesol::optional_base327 constexpr const T& storage() const { 328 return *reinterpret_cast<T const*>(&storage_[0]); 329 } 330 #if defined __GNUC__ 331 #pragma GCC diagnostic pop 332 #endif 333 ~optional_basesol::optional_base334 ~optional_base() { 335 if (init_) { 336 storage().T::~T(); 337 } 338 } 339 }; 340 341 #if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ 342 // Sorry, GCC 4.x; you're just a piece of shit 343 template <typename T> 344 using constexpr_optional_base = optional_base<T>; 345 #else 346 template <class T> 347 struct alignas(T) constexpr_optional_base { 348 char storage_[sizeof(T)]; 349 bool init_; constexpr_optional_basesol::constexpr_optional_base350 constexpr constexpr_optional_base() noexcept 351 : storage_(), init_(false) { 352 } 353 constexpr_optional_basesol::constexpr_optional_base354 explicit constexpr constexpr_optional_base(const T& v) 355 : storage_(), init_(true) { 356 new (&storage()) T(v); 357 } 358 constexpr_optional_basesol::constexpr_optional_base359 explicit constexpr constexpr_optional_base(T&& v) 360 : storage_(), init_(true) { 361 new (&storage()) T(constexpr_move(v)); 362 } 363 364 template <class... Args> constexpr_optional_basesol::constexpr_optional_base365 explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) 366 : init_(true), storage_() { 367 new (&storage()) T(constexpr_forward<Args>(args)...); 368 } 369 370 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> constexpr_optional_basesol::constexpr_optional_base371 OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args) 372 : init_(true), storage_() { 373 new (&storage()) T(il, constexpr_forward<Args>(args)...); 374 } 375 376 #if defined __GNUC__ 377 #pragma GCC diagnostic push 378 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 379 #endif storagesol::constexpr_optional_base380 T& storage() { 381 return (*reinterpret_cast<T*>(&storage_[0])); 382 } 383 storagesol::constexpr_optional_base384 constexpr const T& storage() const { 385 return (*reinterpret_cast<T const*>(&storage_[0])); 386 } 387 #if defined __GNUC__ 388 #pragma GCC diagnostic pop 389 #endif 390 391 ~constexpr_optional_base() = default; 392 }; 393 #endif 394 395 template <class T> 396 using OptionalBase = typename ::std::conditional< 397 ::std::is_trivially_destructible<T>::value, 398 constexpr_optional_base<typename ::std::remove_const<T>::type>, 399 optional_base<typename ::std::remove_const<T>::type>>::type; 400 401 template <class T> 402 class optional : private OptionalBase<T> { 403 static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T"); 404 static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T"); 405 initialized() const406 constexpr bool initialized() const noexcept { 407 return OptionalBase<T>::init_; 408 } dataptr()409 typename ::std::remove_const<T>::type* dataptr() { 410 return ::std::addressof(OptionalBase<T>::storage()); 411 } dataptr() const412 constexpr const T* dataptr() const { 413 return detail_::static_addressof(OptionalBase<T>::storage()); 414 } 415 416 #if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 contained_val() const417 constexpr const T& contained_val() const& { 418 return OptionalBase<T>::storage(); 419 } 420 #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 contained_val()421 OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { 422 return ::std::move(OptionalBase<T>::storage()); 423 } contained_val()424 OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { 425 return OptionalBase<T>::storage(); 426 } 427 #else contained_val()428 T& contained_val() & { 429 return OptionalBase<T>::storage(); 430 } contained_val()431 T&& contained_val() && { 432 return ::std::move(OptionalBase<T>::storage()); 433 } 434 #endif 435 #else contained_val() const436 constexpr const T& contained_val() const { 437 return OptionalBase<T>::storage(); 438 } contained_val()439 T& contained_val() { 440 return OptionalBase<T>::storage(); 441 } 442 #endif 443 clear()444 void clear() noexcept { 445 if (initialized()) 446 dataptr()->T::~T(); 447 OptionalBase<T>::init_ = false; 448 } 449 450 template <class... Args> initialize(Args &&...args)451 void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...))) { 452 assert(!OptionalBase<T>::init_); 453 ::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...); 454 OptionalBase<T>::init_ = true; 455 } 456 457 template <class U, class... Args> initialize(::std::initializer_list<U> il,Args &&...args)458 void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...))) { 459 assert(!OptionalBase<T>::init_); 460 ::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...); 461 OptionalBase<T>::init_ = true; 462 } 463 464 public: 465 typedef T value_type; 466 467 // 20.5.5.1, constructors optional()468 constexpr optional() noexcept 469 : OptionalBase<T>(){}; optional(nullopt_t)470 constexpr optional(nullopt_t) noexcept 471 : OptionalBase<T>(){}; 472 optional(const optional & rhs)473 optional(const optional& rhs) 474 : OptionalBase<T>() { 475 if (rhs.initialized()) { 476 ::new (static_cast<void*>(dataptr())) T(*rhs); 477 OptionalBase<T>::init_ = true; 478 } 479 } 480 optional(const optional<T &> & rhs)481 optional(const optional<T&>& rhs) 482 : optional() { 483 if (rhs) { 484 ::new (static_cast<void*>(dataptr())) T(*rhs); 485 OptionalBase<T>::init_ = true; 486 } 487 } 488 optional(optional && rhs)489 optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value) 490 : OptionalBase<T>() { 491 if (rhs.initialized()) { 492 ::new (static_cast<void*>(dataptr())) T(::std::move(*rhs)); 493 OptionalBase<T>::init_ = true; 494 } 495 } 496 optional(const T & v)497 constexpr optional(const T& v) 498 : OptionalBase<T>(v) { 499 } 500 optional(T && v)501 constexpr optional(T&& v) 502 : OptionalBase<T>(constexpr_move(v)) { 503 } 504 505 template <class... Args> optional(in_place_t,Args &&...args)506 explicit constexpr optional(in_place_t, Args&&... args) 507 : OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) { 508 } 509 510 template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)> optional(in_place_t,::std::initializer_list<U> il,Args &&...args)511 OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args) 512 : OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) { 513 } 514 515 // 20.5.4.2, Destructor 516 ~optional() = default; 517 518 // 20.5.4.3, assignment operator =(nullopt_t)519 optional& operator=(nullopt_t) noexcept { 520 clear(); 521 return *this; 522 } 523 operator =(const optional & rhs)524 optional& operator=(const optional& rhs) { 525 if (initialized() == true && rhs.initialized() == false) 526 clear(); 527 else if (initialized() == false && rhs.initialized() == true) 528 initialize(*rhs); 529 else if (initialized() == true && rhs.initialized() == true) 530 contained_val() = *rhs; 531 return *this; 532 } 533 operator =(optional && rhs)534 optional& operator=(optional&& rhs) noexcept(::std::is_nothrow_move_assignable<T>::value&& ::std::is_nothrow_move_constructible<T>::value) { 535 if (initialized() == true && rhs.initialized() == false) 536 clear(); 537 else if (initialized() == false && rhs.initialized() == true) 538 initialize(::std::move(*rhs)); 539 else if (initialized() == true && rhs.initialized() == true) 540 contained_val() = ::std::move(*rhs); 541 return *this; 542 } 543 544 template <class U> operator =(U && v)545 auto operator=(U&& v) 546 -> typename ::std::enable_if< 547 ::std::is_same<typename ::std::decay<U>::type, T>::value, 548 optional&>::type { 549 if (initialized()) { 550 contained_val() = ::std::forward<U>(v); 551 } 552 else { 553 initialize(::std::forward<U>(v)); 554 } 555 return *this; 556 } 557 558 template <class... Args> emplace(Args &&...args)559 void emplace(Args&&... args) { 560 clear(); 561 initialize(::std::forward<Args>(args)...); 562 } 563 564 template <class U, class... Args> emplace(::std::initializer_list<U> il,Args &&...args)565 void emplace(::std::initializer_list<U> il, Args&&... args) { 566 clear(); 567 initialize<U, Args...>(il, ::std::forward<Args>(args)...); 568 } 569 570 // 20.5.4.4, Swap swap(optional<T> & rhs)571 void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value&& noexcept(swap(::std::declval<T&>(), ::std::declval<T&>()))) { 572 if (initialized() == true && rhs.initialized() == false) { 573 rhs.initialize(::std::move(**this)); 574 clear(); 575 } 576 else if (initialized() == false && rhs.initialized() == true) { 577 initialize(::std::move(*rhs)); 578 rhs.clear(); 579 } 580 else if (initialized() == true && rhs.initialized() == true) { 581 using ::std::swap; 582 swap(**this, *rhs); 583 } 584 } 585 586 // 20.5.4.5, Observers 587 operator bool() const588 explicit constexpr operator bool() const noexcept { 589 return initialized(); 590 } 591 operator ->() const592 constexpr T const* operator->() const { 593 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); 594 } 595 596 #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 597 operator ->()598 OPTIONAL_MUTABLE_CONSTEXPR T* operator->() { 599 assert(initialized()); 600 return dataptr(); 601 } 602 operator *() const603 constexpr T const& operator*() const& { 604 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); 605 } 606 operator *()607 OPTIONAL_MUTABLE_CONSTEXPR T& operator*() & { 608 assert(initialized()); 609 return contained_val(); 610 } 611 operator *()612 OPTIONAL_MUTABLE_CONSTEXPR T&& operator*() && { 613 assert(initialized()); 614 return constexpr_move(contained_val()); 615 } 616 value() const617 constexpr T const& value() const& { 618 return initialized() ? contained_val() 619 #ifdef SOL_NO_EXCEPTIONS 620 // we can't abort here 621 // because there's no constexpr abort 622 : *static_cast<T*>(nullptr); 623 #else 624 : (throw bad_optional_access("bad optional access"), contained_val()); 625 #endif 626 } 627 value()628 OPTIONAL_MUTABLE_CONSTEXPR T& value() & { 629 return initialized() ? contained_val() 630 #ifdef SOL_NO_EXCEPTIONS 631 : *static_cast<T*>(nullptr); 632 #else 633 : (throw bad_optional_access("bad optional access"), contained_val()); 634 #endif 635 } 636 value()637 OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { 638 return initialized() ? contained_val() 639 #ifdef SOL_NO_EXCEPTIONS 640 // we can't abort here 641 // because there's no constexpr abort 642 : std::move(*static_cast<T*>(nullptr)); 643 #else 644 : (throw bad_optional_access("bad optional access"), contained_val()); 645 #endif 646 } 647 648 #else 649 operator ->()650 T* operator->() { 651 assert(initialized()); 652 return dataptr(); 653 } 654 operator *() const655 constexpr T const& operator*() const { 656 return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); 657 } 658 operator *()659 T& operator*() { 660 assert(initialized()); 661 return contained_val(); 662 } 663 value() const664 constexpr T const& value() const { 665 return initialized() ? contained_val() 666 #ifdef SOL_NO_EXCEPTIONS 667 // we can't abort here 668 // because there's no constexpr abort 669 : *static_cast<T*>(nullptr); 670 #else 671 : (throw bad_optional_access("bad optional access"), contained_val()); 672 #endif 673 } 674 value()675 T& value() { 676 return initialized() ? contained_val() 677 #ifdef SOL_NO_EXCEPTIONS 678 // we can abort here 679 // but the others are constexpr, so we can't... 680 : (std::abort(), *static_cast<T*>(nullptr)); 681 #else 682 : (throw bad_optional_access("bad optional access"), contained_val()); 683 #endif 684 } 685 686 #endif 687 688 #if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 689 690 template <class V> value_or(V && v) const691 constexpr T value_or(V&& v) const& { 692 return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); 693 } 694 695 #if OPTIONAL_HAS_MOVE_ACCESSORS == 1 696 697 template <class V> value_or(V && v)698 OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && { 699 return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); 700 } 701 702 #else 703 704 template <class V> value_or(V && v)705 T value_or(V&& v) && { 706 return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v)); 707 } 708 709 #endif 710 711 #else 712 713 template <class V> value_or(V && v) const714 constexpr T value_or(V&& v) const { 715 return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v)); 716 } 717 718 #endif 719 }; 720 721 template <class T> 722 class optional<T&> { 723 static_assert(!::std::is_same<T, nullopt_t>::value, "bad T"); 724 static_assert(!::std::is_same<T, in_place_t>::value, "bad T"); 725 T* ref; 726 727 public: 728 // 20.5.5.1, construction/destruction optional()729 constexpr optional() noexcept 730 : ref(nullptr) { 731 } 732 optional(nullopt_t)733 constexpr optional(nullopt_t) noexcept 734 : ref(nullptr) { 735 } 736 optional(T & v)737 constexpr optional(T& v) noexcept 738 : ref(detail_::static_addressof(v)) { 739 } 740 741 optional(T&&) = delete; 742 optional(const optional & rhs)743 constexpr optional(const optional& rhs) noexcept 744 : ref(rhs.ref) { 745 } 746 optional(in_place_t,T & v)747 explicit constexpr optional(in_place_t, T& v) noexcept 748 : ref(detail_::static_addressof(v)) { 749 } 750 751 explicit optional(in_place_t, T&&) = delete; 752 753 ~optional() = default; 754 755 // 20.5.5.2, mutation operator =(nullopt_t)756 optional& operator=(nullopt_t) noexcept { 757 ref = nullptr; 758 return *this; 759 } 760 761 // optional& operator=(const optional& rhs) noexcept { 762 // ref = rhs.ref; 763 // return *this; 764 // } 765 766 // optional& operator=(optional&& rhs) noexcept { 767 // ref = rhs.ref; 768 // return *this; 769 // } 770 771 template <typename U> operator =(U && rhs)772 auto operator=(U&& rhs) noexcept 773 -> typename ::std::enable_if< 774 ::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, 775 optional&>::type { 776 ref = rhs.ref; 777 return *this; 778 } 779 780 template <typename U> 781 auto operator=(U&& rhs) noexcept 782 -> typename ::std::enable_if< 783 !::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value, 784 optional&>::type = delete; 785 emplace(T & v)786 void emplace(T& v) noexcept { 787 ref = detail_::static_addressof(v); 788 } 789 790 void emplace(T&&) = delete; 791 swap(optional<T &> & rhs)792 void swap(optional<T&>& rhs) noexcept { 793 ::std::swap(ref, rhs.ref); 794 } 795 796 // 20.5.5.3, observers operator ->() const797 constexpr T* operator->() const { 798 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); 799 } 800 operator *() const801 constexpr T& operator*() const { 802 return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); 803 } 804 value() const805 constexpr T& value() const { 806 #ifdef SOL_NO_EXCEPTIONS 807 return *ref; 808 #else 809 return ref ? *ref 810 : (throw bad_optional_access("bad optional access"), *ref); 811 #endif // Exceptions 812 } 813 operator bool() const814 explicit constexpr operator bool() const noexcept { 815 return ref != nullptr; 816 } 817 818 template <typename V> value_or(V && v) const819 constexpr T& value_or(V&& v) const { 820 return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v)); 821 } 822 }; 823 824 template <class T> 825 class optional<T&&> { 826 static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); 827 }; 828 829 // 20.5.8, Relational operators 830 template <class T> operator ==(const optional<T> & x,const optional<T> & y)831 constexpr bool operator==(const optional<T>& x, const optional<T>& y) { 832 return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; 833 } 834 835 template <class T> operator !=(const optional<T> & x,const optional<T> & y)836 constexpr bool operator!=(const optional<T>& x, const optional<T>& y) { 837 return !(x == y); 838 } 839 840 template <class T> operator <(const optional<T> & x,const optional<T> & y)841 constexpr bool operator<(const optional<T>& x, const optional<T>& y) { 842 return (!y) ? false : (!x) ? true : *x < *y; 843 } 844 845 template <class T> operator >(const optional<T> & x,const optional<T> & y)846 constexpr bool operator>(const optional<T>& x, const optional<T>& y) { 847 return (y < x); 848 } 849 850 template <class T> operator <=(const optional<T> & x,const optional<T> & y)851 constexpr bool operator<=(const optional<T>& x, const optional<T>& y) { 852 return !(y < x); 853 } 854 855 template <class T> operator >=(const optional<T> & x,const optional<T> & y)856 constexpr bool operator>=(const optional<T>& x, const optional<T>& y) { 857 return !(x < y); 858 } 859 860 // 20.5.9, Comparison with nullopt 861 template <class T> operator ==(const optional<T> & x,nullopt_t)862 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept { 863 return (!x); 864 } 865 866 template <class T> operator ==(nullopt_t,const optional<T> & x)867 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept { 868 return (!x); 869 } 870 871 template <class T> operator !=(const optional<T> & x,nullopt_t)872 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept { 873 return bool(x); 874 } 875 876 template <class T> operator !=(nullopt_t,const optional<T> & x)877 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept { 878 return bool(x); 879 } 880 881 template <class T> operator <(const optional<T> &,nullopt_t)882 constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { 883 return false; 884 } 885 886 template <class T> operator <(nullopt_t,const optional<T> & x)887 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept { 888 return bool(x); 889 } 890 891 template <class T> operator <=(const optional<T> & x,nullopt_t)892 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept { 893 return (!x); 894 } 895 896 template <class T> operator <=(nullopt_t,const optional<T> &)897 constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { 898 return true; 899 } 900 901 template <class T> operator >(const optional<T> & x,nullopt_t)902 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept { 903 return bool(x); 904 } 905 906 template <class T> operator >(nullopt_t,const optional<T> &)907 constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { 908 return false; 909 } 910 911 template <class T> operator >=(const optional<T> &,nullopt_t)912 constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { 913 return true; 914 } 915 916 template <class T> operator >=(nullopt_t,const optional<T> & x)917 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept { 918 return (!x); 919 } 920 921 // 20.5.10, Comparison with T 922 template <class T> operator ==(const optional<T> & x,const T & v)923 constexpr bool operator==(const optional<T>& x, const T& v) { 924 return bool(x) ? *x == v : false; 925 } 926 927 template <class T> operator ==(const T & v,const optional<T> & x)928 constexpr bool operator==(const T& v, const optional<T>& x) { 929 return bool(x) ? v == *x : false; 930 } 931 932 template <class T> operator !=(const optional<T> & x,const T & v)933 constexpr bool operator!=(const optional<T>& x, const T& v) { 934 return bool(x) ? *x != v : true; 935 } 936 937 template <class T> operator !=(const T & v,const optional<T> & x)938 constexpr bool operator!=(const T& v, const optional<T>& x) { 939 return bool(x) ? v != *x : true; 940 } 941 942 template <class T> operator <(const optional<T> & x,const T & v)943 constexpr bool operator<(const optional<T>& x, const T& v) { 944 return bool(x) ? *x < v : true; 945 } 946 947 template <class T> operator >(const T & v,const optional<T> & x)948 constexpr bool operator>(const T& v, const optional<T>& x) { 949 return bool(x) ? v > *x : true; 950 } 951 952 template <class T> operator >(const optional<T> & x,const T & v)953 constexpr bool operator>(const optional<T>& x, const T& v) { 954 return bool(x) ? *x > v : false; 955 } 956 957 template <class T> operator <(const T & v,const optional<T> & x)958 constexpr bool operator<(const T& v, const optional<T>& x) { 959 return bool(x) ? v < *x : false; 960 } 961 962 template <class T> operator >=(const optional<T> & x,const T & v)963 constexpr bool operator>=(const optional<T>& x, const T& v) { 964 return bool(x) ? *x >= v : false; 965 } 966 967 template <class T> operator <=(const T & v,const optional<T> & x)968 constexpr bool operator<=(const T& v, const optional<T>& x) { 969 return bool(x) ? v <= *x : false; 970 } 971 972 template <class T> operator <=(const optional<T> & x,const T & v)973 constexpr bool operator<=(const optional<T>& x, const T& v) { 974 return bool(x) ? *x <= v : true; 975 } 976 977 template <class T> operator >=(const T & v,const optional<T> & x)978 constexpr bool operator>=(const T& v, const optional<T>& x) { 979 return bool(x) ? v >= *x : true; 980 } 981 982 // Comparison of optional<T&> with T 983 template <class T> operator ==(const optional<T &> & x,const T & v)984 constexpr bool operator==(const optional<T&>& x, const T& v) { 985 return bool(x) ? *x == v : false; 986 } 987 988 template <class T> operator ==(const T & v,const optional<T &> & x)989 constexpr bool operator==(const T& v, const optional<T&>& x) { 990 return bool(x) ? v == *x : false; 991 } 992 993 template <class T> operator !=(const optional<T &> & x,const T & v)994 constexpr bool operator!=(const optional<T&>& x, const T& v) { 995 return bool(x) ? *x != v : true; 996 } 997 998 template <class T> operator !=(const T & v,const optional<T &> & x)999 constexpr bool operator!=(const T& v, const optional<T&>& x) { 1000 return bool(x) ? v != *x : true; 1001 } 1002 1003 template <class T> operator <(const optional<T &> & x,const T & v)1004 constexpr bool operator<(const optional<T&>& x, const T& v) { 1005 return bool(x) ? *x < v : true; 1006 } 1007 1008 template <class T> operator >(const T & v,const optional<T &> & x)1009 constexpr bool operator>(const T& v, const optional<T&>& x) { 1010 return bool(x) ? v > *x : true; 1011 } 1012 1013 template <class T> operator >(const optional<T &> & x,const T & v)1014 constexpr bool operator>(const optional<T&>& x, const T& v) { 1015 return bool(x) ? *x > v : false; 1016 } 1017 1018 template <class T> operator <(const T & v,const optional<T &> & x)1019 constexpr bool operator<(const T& v, const optional<T&>& x) { 1020 return bool(x) ? v < *x : false; 1021 } 1022 1023 template <class T> operator >=(const optional<T &> & x,const T & v)1024 constexpr bool operator>=(const optional<T&>& x, const T& v) { 1025 return bool(x) ? *x >= v : false; 1026 } 1027 1028 template <class T> operator <=(const T & v,const optional<T &> & x)1029 constexpr bool operator<=(const T& v, const optional<T&>& x) { 1030 return bool(x) ? v <= *x : false; 1031 } 1032 1033 template <class T> operator <=(const optional<T &> & x,const T & v)1034 constexpr bool operator<=(const optional<T&>& x, const T& v) { 1035 return bool(x) ? *x <= v : true; 1036 } 1037 1038 template <class T> operator >=(const T & v,const optional<T &> & x)1039 constexpr bool operator>=(const T& v, const optional<T&>& x) { 1040 return bool(x) ? v >= *x : true; 1041 } 1042 1043 // Comparison of optional<T const&> with T 1044 template <class T> operator ==(const optional<const T &> & x,const T & v)1045 constexpr bool operator==(const optional<const T&>& x, const T& v) { 1046 return bool(x) ? *x == v : false; 1047 } 1048 1049 template <class T> operator ==(const T & v,const optional<const T &> & x)1050 constexpr bool operator==(const T& v, const optional<const T&>& x) { 1051 return bool(x) ? v == *x : false; 1052 } 1053 1054 template <class T> operator !=(const optional<const T &> & x,const T & v)1055 constexpr bool operator!=(const optional<const T&>& x, const T& v) { 1056 return bool(x) ? *x != v : true; 1057 } 1058 1059 template <class T> operator !=(const T & v,const optional<const T &> & x)1060 constexpr bool operator!=(const T& v, const optional<const T&>& x) { 1061 return bool(x) ? v != *x : true; 1062 } 1063 1064 template <class T> operator <(const optional<const T &> & x,const T & v)1065 constexpr bool operator<(const optional<const T&>& x, const T& v) { 1066 return bool(x) ? *x < v : true; 1067 } 1068 1069 template <class T> operator >(const T & v,const optional<const T &> & x)1070 constexpr bool operator>(const T& v, const optional<const T&>& x) { 1071 return bool(x) ? v > *x : true; 1072 } 1073 1074 template <class T> operator >(const optional<const T &> & x,const T & v)1075 constexpr bool operator>(const optional<const T&>& x, const T& v) { 1076 return bool(x) ? *x > v : false; 1077 } 1078 1079 template <class T> operator <(const T & v,const optional<const T &> & x)1080 constexpr bool operator<(const T& v, const optional<const T&>& x) { 1081 return bool(x) ? v < *x : false; 1082 } 1083 1084 template <class T> operator >=(const optional<const T &> & x,const T & v)1085 constexpr bool operator>=(const optional<const T&>& x, const T& v) { 1086 return bool(x) ? *x >= v : false; 1087 } 1088 1089 template <class T> operator <=(const T & v,const optional<const T &> & x)1090 constexpr bool operator<=(const T& v, const optional<const T&>& x) { 1091 return bool(x) ? v <= *x : false; 1092 } 1093 1094 template <class T> operator <=(const optional<const T &> & x,const T & v)1095 constexpr bool operator<=(const optional<const T&>& x, const T& v) { 1096 return bool(x) ? *x <= v : true; 1097 } 1098 1099 template <class T> operator >=(const T & v,const optional<const T &> & x)1100 constexpr bool operator>=(const T& v, const optional<const T&>& x) { 1101 return bool(x) ? v >= *x : true; 1102 } 1103 1104 // 20.5.12, Specialized algorithms 1105 template <class T> swap(optional<T> & x,optional<T> & y)1106 void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) { 1107 x.swap(y); 1108 } 1109 1110 template <class T> make_optional(T && v)1111 constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) { 1112 return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v)); 1113 } 1114 1115 template <class X> make_optional(::std::reference_wrapper<X> v)1116 constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) { 1117 return optional<X&>(v.get()); 1118 } 1119 1120 } // namespace sol 1121 1122 namespace std { 1123 template <typename T> 1124 struct hash<sol::optional<T>> { 1125 typedef typename hash<T>::result_type result_type; 1126 typedef sol::optional<T> argument_type; 1127 operator ()std::hash1128 constexpr result_type operator()(argument_type const& arg) const { 1129 return arg ? ::std::hash<T>{}(*arg) : result_type{}; 1130 } 1131 }; 1132 1133 template <typename T> 1134 struct hash<sol::optional<T&>> { 1135 typedef typename hash<T>::result_type result_type; 1136 typedef sol::optional<T&> argument_type; 1137 operator ()std::hash1138 constexpr result_type operator()(argument_type const& arg) const { 1139 return arg ? ::std::hash<T>{}(*arg) : result_type{}; 1140 } 1141 }; 1142 } // namespace std 1143 1144 #if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ 1145 #pragma warning(pop) 1146 #endif 1147 1148 #undef TR2_OPTIONAL_REQUIRES 1149 #undef TR2_OPTIONAL_ASSERTED_EXPRESSION 1150 1151 #endif // SOL_OPTIONAL_IMPLEMENTATION_HPP 1152