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