1 // The MIT License (MIT) 2 3 // Copyright (c) 2013-2021 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 // Taken from: TartanLlama/optional on Github, because 23 // holy shit am I done dealing with C++11 constexpr 24 25 /// 26 // optional - An implementation of std::optional with extensions 27 // Written in 2017 by Simon Brand (@TartanLlama) 28 // 29 // To the extent possible under law, the author(s) have dedicated all 30 // copyright and related and neighboring rights to this software to the 31 // public domain worldwide. This software is distributed without any warranty. 32 // 33 // You should have received a copy of the CC0 Public Domain Dedication 34 // along with this software. If not, see 35 // <http://creativecommons.org/publicdomain/zero/1.0/>. 36 /// 37 38 #ifndef SOL_TL_OPTIONAL_HPP 39 #define SOL_TL_OPTIONAL_HPP 40 41 #include <sol/version.hpp> 42 43 #include <sol/in_place.hpp> 44 45 #define SOL_TL_OPTIONAL_VERSION_MAJOR 0 46 #define SOL_TL_OPTIONAL_VERSION_MINOR 5 47 48 #include <exception> 49 #include <functional> 50 #include <new> 51 #include <type_traits> 52 #include <utility> 53 #include <cstdlib> 54 #include <optional> 55 56 #if (defined(_MSC_VER) && _MSC_VER == 1900) 57 #define SOL_TL_OPTIONAL_MSVC2015 58 #endif 59 60 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) 61 #define SOL_TL_OPTIONAL_GCC49 62 #endif 63 64 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__)) 65 #define SOL_TL_OPTIONAL_GCC54 66 #endif 67 68 #if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__)) 69 #define SOL_TL_OPTIONAL_GCC55 70 #endif 71 72 #if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) 73 // GCC < 5 doesn't support overloading on const&& for member functions 74 #define SOL_TL_OPTIONAL_NO_CONSTRR 75 76 // GCC < 5 doesn't support some standard C++11 type traits 77 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor<T>::value 78 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign<T>::value 79 80 // This one will be different for GCC 5.7 if it's ever supported 81 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 82 83 // GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector 84 // for non-copyable types 85 #elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) 86 #ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX 87 #define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX 88 namespace sol { namespace detail { 89 template <class T> 90 struct is_trivially_copy_constructible : std::is_trivially_copy_constructible<T> { }; 91 #ifdef _GLIBCXX_VECTOR 92 template <class T, class A> 93 struct is_trivially_copy_constructible<std::vector<T, A>> : std::is_trivially_copy_constructible<T> { }; 94 #endif 95 }} // namespace sol::detail 96 #endif 97 98 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible<T>::value 99 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value 100 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 101 #else 102 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible<T>::value 103 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable<T>::value 104 #define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible<T>::value 105 #endif 106 107 #if __cplusplus > 201103L 108 #define SOL_TL_OPTIONAL_CXX14 109 #endif 110 111 // constexpr implies const in C++11, not C++14 112 #if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49)) 113 /// \exclude 114 #define SOL_TL_OPTIONAL_11_CONSTEXPR 115 #else 116 /// \exclude 117 #define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr 118 #endif 119 120 namespace sol { 121 #ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX 122 #define SOL_TL_MONOSTATE_INPLACE_MUTEX 123 /// \brief Used to represent an optional with no data; essentially a bool 124 class monostate { }; 125 #endif 126 127 template <class T> 128 class optional; 129 130 /// \exclude 131 namespace detail { 132 #ifndef SOL_TL_TRAITS_MUTEX 133 #define SOL_TL_TRAITS_MUTEX 134 // C++14-style aliases for brevity 135 template <class T> 136 using remove_const_t = typename std::remove_const<T>::type; 137 template <class T> 138 using remove_reference_t = typename std::remove_reference<T>::type; 139 template <class T> 140 using decay_t = typename std::decay<T>::type; 141 template <bool E, class T = void> 142 using enable_if_t = typename std::enable_if<E, T>::type; 143 template <bool B, class T, class F> 144 using conditional_t = typename std::conditional<B, T, F>::type; 145 146 // std::conjunction from C++17 147 template <class...> 148 struct conjunction : std::true_type { }; 149 template <class B> 150 struct conjunction<B> : B { }; 151 template <class B, class... Bs> 152 struct conjunction<B, Bs...> : std::conditional<bool(B::value), conjunction<Bs...>, B>::type { }; 153 154 #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L 155 #define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 156 #endif 157 158 // In C++11 mode, there's an issue in libc++'s std::mem_fn 159 // which results in a hard-error when using it in a noexcept expression 160 // in some cases. This is a check to workaround the common failing case. 161 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 162 template <class T> 163 struct is_pointer_to_non_const_member_func : std::false_type { }; 164 template <class T, class Ret, class... Args> 165 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)> : std::true_type { }; 166 template <class T, class Ret, class... Args> 167 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...)&> : std::true_type { }; 168 template <class T, class Ret, class... Args> 169 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) &&> : std::true_type { }; 170 template <class T, class Ret, class... Args> 171 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile> : std::true_type { }; 172 template <class T, class Ret, class... Args> 173 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&> : std::true_type { }; 174 template <class T, class Ret, class... Args> 175 struct is_pointer_to_non_const_member_func<Ret (T::*)(Args...) volatile&&> : std::true_type { }; 176 177 template <class T> 178 struct is_const_or_const_ref : std::false_type { }; 179 template <class T> 180 struct is_const_or_const_ref<T const&> : std::true_type { }; 181 template <class T> 182 struct is_const_or_const_ref<T const> : std::true_type { }; 183 #endif 184 185 // std::invoke from C++17 186 // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround 187 template <typename Fn, typename... Args, 188 #ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND 189 typename = enable_if_t<!(is_pointer_to_non_const_member_func<Fn>::value && is_const_or_const_ref<Args...>::value)>, 190 #endif 191 typename = enable_if_t<std::is_member_pointer<decay_t<Fn>>::value>, int = 0> invoke(Fn && f,Args &&...args)192 constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward<Args>(args)...))) 193 -> decltype(std::mem_fn(f)(std::forward<Args>(args)...)) { 194 return std::mem_fn(f)(std::forward<Args>(args)...); 195 } 196 197 template <typename Fn, typename... Args, typename = enable_if_t<!std::is_member_pointer<decay_t<Fn>>::value>> invoke(Fn && f,Args &&...args)198 constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward<Fn>(f)(std::forward<Args>(args)...))) 199 -> decltype(std::forward<Fn>(f)(std::forward<Args>(args)...)) { 200 return std::forward<Fn>(f)(std::forward<Args>(args)...); 201 } 202 203 // std::invoke_result from C++17 204 template <class F, class, class... Us> 205 struct invoke_result_impl; 206 207 template <class F, class... Us> 208 struct invoke_result_impl<F, decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...), void()), Us...> { 209 using type = decltype(detail::invoke(std::declval<F>(), std::declval<Us>()...)); 210 }; 211 212 template <class F, class... Us> 213 using invoke_result = invoke_result_impl<F, void, Us...>; 214 215 template <class F, class... Us> 216 using invoke_result_t = typename invoke_result<F, Us...>::type; 217 #endif 218 219 // std::void_t from C++17 220 template <class...> 221 struct voider { 222 using type = void; 223 }; 224 template <class... Ts> 225 using void_t = typename voider<Ts...>::type; 226 227 // Trait for checking if a type is a sol::optional 228 template <class T> 229 struct is_optional_impl : std::false_type { }; 230 template <class T> 231 struct is_optional_impl<optional<T>> : std::true_type { }; 232 template <class T> 233 using is_optional = is_optional_impl<decay_t<T>>; 234 235 // Change void to sol::monostate 236 template <class U> 237 using fixup_void = conditional_t<std::is_void<U>::value, monostate, U>; 238 239 template <class F, class U, class = invoke_result_t<F, U>> 240 using get_map_return = optional<fixup_void<invoke_result_t<F, U>>>; 241 242 // Check if invoking F for some Us returns void 243 template <class F, class = void, class... U> 244 struct returns_void_impl; 245 template <class F, class... U> 246 struct returns_void_impl<F, void_t<invoke_result_t<F, U...>>, U...> : std::is_void<invoke_result_t<F, U...>> { }; 247 template <class F, class... U> 248 using returns_void = returns_void_impl<F, void, U...>; 249 250 template <class T, class... U> 251 using enable_if_ret_void = enable_if_t<returns_void<T&&, U...>::value>; 252 253 template <class T, class... U> 254 using disable_if_ret_void = enable_if_t<!returns_void<T&&, U...>::value>; 255 256 template <class T, class U> 257 using enable_forward_value = detail::enable_if_t<std::is_constructible<T, U&&>::value && !std::is_same<detail::decay_t<U>, in_place_t>::value 258 && !std::is_same<optional<T>, detail::decay_t<U>>::value>; 259 260 template <class T, class U, class Other> 261 using enable_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && !std::is_constructible<T, optional<U>&>::value 262 && !std::is_constructible<T, optional<U>&&>::value && !std::is_constructible<T, const optional<U>&>::value 263 && !std::is_constructible<T, const optional<U>&&>::value && !std::is_convertible<optional<U>&, T>::value 264 && !std::is_convertible<optional<U>&&, T>::value && !std::is_convertible<const optional<U>&, T>::value 265 && !std::is_convertible<const optional<U>&&, T>::value>; 266 267 template <class T, class U> 268 using enable_assign_forward = detail::enable_if_t<!std::is_same<optional<T>, detail::decay_t<U>>::value 269 && !detail::conjunction<std::is_scalar<T>, std::is_same<T, detail::decay_t<U>>>::value && std::is_constructible<T, U>::value 270 && std::is_assignable<T&, U>::value>; 271 272 template <class T, class U, class Other> 273 using enable_assign_from_other = detail::enable_if_t<std::is_constructible<T, Other>::value && std::is_assignable<T&, Other>::value 274 && !std::is_constructible<T, optional<U>&>::value && !std::is_constructible<T, optional<U>&&>::value 275 && !std::is_constructible<T, const optional<U>&>::value && !std::is_constructible<T, const optional<U>&&>::value 276 && !std::is_convertible<optional<U>&, T>::value && !std::is_convertible<optional<U>&&, T>::value 277 && !std::is_convertible<const optional<U>&, T>::value && !std::is_convertible<const optional<U>&&, T>::value 278 && !std::is_assignable<T&, optional<U>&>::value && !std::is_assignable<T&, optional<U>&&>::value 279 && !std::is_assignable<T&, const optional<U>&>::value && !std::is_assignable<T&, const optional<U>&&>::value>; 280 281 #ifdef _MSC_VER 282 // TODO make a version which works with MSVC 283 template <class T, class U = T> 284 struct is_swappable : std::true_type { }; 285 286 template <class T, class U = T> 287 struct is_nothrow_swappable : std::true_type { }; 288 #else 289 // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept 290 namespace swap_adl_tests { 291 // if swap ADL finds this then it would call std::swap otherwise (same 292 // signature) 293 struct tag { }; 294 295 template <class T> 296 tag swap(T&, T&); 297 template <class T, std::size_t N> 298 tag swap(T (&a)[N], T (&b)[N]); 299 300 // helper functions to test if an unqualified swap is possible, and if it 301 // becomes std::swap 302 template <class, class> 303 std::false_type can_swap(...) noexcept(false); 304 template <class T, class U, class = decltype(swap(std::declval<T&>(), std::declval<U&>()))> 305 std::true_type can_swap(int) noexcept(noexcept(swap(std::declval<T&>(), std::declval<U&>()))); 306 307 template <class, class> 308 std::false_type uses_std(...); 309 template <class T, class U> 310 std::is_same<decltype(swap(std::declval<T&>(), std::declval<U&>())), tag> uses_std(int); 311 312 template <class T> 313 struct is_std_swap_noexcept 314 : std::integral_constant<bool, std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value> { }; 315 316 template <class T, std::size_t N> 317 struct is_std_swap_noexcept<T[N]> : is_std_swap_noexcept<T> { }; 318 319 template <class T, class U> 320 struct is_adl_swap_noexcept : std::integral_constant<bool, noexcept(can_swap<T, U>(0))> { }; 321 } // namespace swap_adl_tests 322 323 template <class T, class U = T> 324 struct is_swappable : std::integral_constant<bool, 325 decltype(detail::swap_adl_tests::can_swap<T, U>(0))::value 326 && (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value 327 || (std::is_move_assignable<T>::value && std::is_move_constructible<T>::value))> { }; 328 329 template <class T, std::size_t N> 330 struct is_swappable<T[N], T[N]> : std::integral_constant<bool, 331 decltype(detail::swap_adl_tests::can_swap<T[N], T[N]>(0))::value 332 && (!decltype(detail::swap_adl_tests::uses_std<T[N], T[N]>(0))::value || is_swappable<T, T>::value)> { }; 333 334 template <class T, class U = T> 335 struct is_nothrow_swappable 336 : std::integral_constant<bool, 337 is_swappable<T, U>::value 338 && ((decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept<T>::value) 339 || (!decltype(detail::swap_adl_tests::uses_std<T, U>(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept<T, U>::value))> { }; 340 #endif 341 342 // The storage base manages the actual storage, and correctly propagates 343 // trivial destroyion from T. This case is for when T is not trivially 344 // destructible. 345 template <class T, bool = ::std::is_trivially_destructible<T>::value> 346 struct optional_storage_base { optional_storage_basesol::detail::optional_storage_base347 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { 348 } 349 350 template <class... U> optional_storage_basesol::detail::optional_storage_base351 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) { 352 } 353 ~optional_storage_basesol::detail::optional_storage_base354 ~optional_storage_base() { 355 if (m_has_value) { 356 m_value.~T(); 357 m_has_value = false; 358 } 359 } 360 361 struct dummy { }; 362 union { 363 dummy m_dummy; 364 T m_value; 365 }; 366 367 bool m_has_value; 368 }; 369 370 // This case is for when T is trivially destructible. 371 template <class T> 372 struct optional_storage_base<T, true> { optional_storage_basesol::detail::optional_storage_base373 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { 374 } 375 376 template <class... U> optional_storage_basesol::detail::optional_storage_base377 SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward<U>(u)...), m_has_value(true) { 378 } 379 380 // No destructor, so this class is trivially destructible 381 382 struct dummy { }; 383 union { 384 dummy m_dummy; 385 T m_value; 386 }; 387 388 bool m_has_value = false; 389 }; 390 391 // This base class provides some handy member functions which can be used in 392 // further derived classes 393 template <class T> 394 struct optional_operations_base : optional_storage_base<T> { 395 using optional_storage_base<T>::optional_storage_base; 396 hard_resetsol::detail::optional_operations_base397 void hard_reset() noexcept { 398 get().~T(); 399 this->m_has_value = false; 400 } 401 402 template <class... Args> constructsol::detail::optional_operations_base403 void construct(Args&&... args) noexcept { 404 new (std::addressof(this->m_value)) T(std::forward<Args>(args)...); 405 this->m_has_value = true; 406 } 407 408 template <class Opt> assignsol::detail::optional_operations_base409 void assign(Opt&& rhs) { 410 if (this->has_value()) { 411 if (rhs.has_value()) { 412 this->m_value = std::forward<Opt>(rhs).get(); 413 } 414 else { 415 this->m_value.~T(); 416 this->m_has_value = false; 417 } 418 } 419 420 else if (rhs.has_value()) { 421 construct(std::forward<Opt>(rhs).get()); 422 } 423 } 424 has_valuesol::detail::optional_operations_base425 bool has_value() const { 426 return this->m_has_value; 427 } 428 getsol::detail::optional_operations_base429 SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & { 430 return this->m_value; 431 } getsol::detail::optional_operations_base432 SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& { 433 return this->m_value; 434 } getsol::detail::optional_operations_base435 SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && { 436 return std::move(this->m_value); 437 } 438 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR getsol::detail::optional_operations_base439 constexpr const T&& get() const&& { 440 return std::move(this->m_value); 441 } 442 #endif 443 }; 444 445 // This class manages conditionally having a trivial copy constructor 446 // This specialization is for when T is trivially copy constructible 447 template <class T, bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T)> 448 struct optional_copy_base : optional_operations_base<T> { 449 using optional_operations_base<T>::optional_operations_base; 450 }; 451 452 // This specialization is for when T is not trivially copy constructible 453 template <class T> 454 struct optional_copy_base<T, false> : optional_operations_base<T> { 455 using base_t = optional_operations_base<T>; 456 457 using base_t::base_t; 458 459 optional_copy_base() = default; optional_copy_basesol::detail::optional_copy_base460 optional_copy_base(const optional_copy_base& rhs) : base_t() { 461 if (rhs.has_value()) { 462 this->construct(rhs.get()); 463 } 464 else { 465 this->m_has_value = false; 466 } 467 } 468 469 optional_copy_base(optional_copy_base&& rhs) = default; 470 optional_copy_base& operator=(const optional_copy_base& rhs) = default; 471 optional_copy_base& operator=(optional_copy_base&& rhs) = default; 472 }; 473 474 // This class manages conditionally having a trivial move constructor 475 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it 476 // doesn't implement an analogue to std::is_trivially_move_constructible. We 477 // have to make do with a non-trivial move constructor even if T is trivially 478 // move constructible 479 #ifndef SOL_TL_OPTIONAL_GCC49 480 template <class T, bool = std::is_trivially_move_constructible<T>::value> 481 struct optional_move_base : optional_copy_base<T> { 482 using optional_copy_base<T>::optional_copy_base; 483 }; 484 #else 485 template <class T, bool = false> 486 struct optional_move_base; 487 #endif 488 template <class T> 489 struct optional_move_base<T, false> : optional_copy_base<T> { 490 using optional_copy_base<T>::optional_copy_base; 491 492 optional_move_base() = default; 493 optional_move_base(const optional_move_base& rhs) = default; 494 optional_move_basesol::detail::optional_move_base495 optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible<T>::value) { 496 if (rhs.has_value()) { 497 this->construct(std::move(rhs.get())); 498 } 499 else { 500 this->m_has_value = false; 501 } 502 } 503 optional_move_base& operator=(const optional_move_base& rhs) = default; 504 optional_move_base& operator=(optional_move_base&& rhs) = default; 505 }; 506 507 // This class manages conditionally having a trivial copy assignment operator 508 template <class T, 509 bool = SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) && SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) 510 && SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T)> 511 struct optional_copy_assign_base : optional_move_base<T> { 512 using optional_move_base<T>::optional_move_base; 513 }; 514 515 template <class T> 516 struct optional_copy_assign_base<T, false> : optional_move_base<T> { 517 using optional_move_base<T>::optional_move_base; 518 519 optional_copy_assign_base() = default; 520 optional_copy_assign_base(const optional_copy_assign_base& rhs) = default; 521 522 optional_copy_assign_base(optional_copy_assign_base&& rhs) = default; operator =sol::detail::optional_copy_assign_base523 optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) { 524 this->assign(rhs); 525 return *this; 526 } 527 optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default; 528 }; 529 530 // This class manages conditionally having a trivial move assignment operator 531 // Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it 532 // doesn't implement an analogue to std::is_trivially_move_assignable. We have 533 // to make do with a non-trivial move assignment operator even if T is trivially 534 // move assignable 535 #ifndef SOL_TL_OPTIONAL_GCC49 536 template <class T, 537 bool = std::is_trivially_destructible<T>::value&& std::is_trivially_move_constructible<T>::value&& std::is_trivially_move_assignable<T>::value> 538 struct optional_move_assign_base : optional_copy_assign_base<T> { 539 using optional_copy_assign_base<T>::optional_copy_assign_base; 540 }; 541 #else 542 template <class T, bool = false> 543 struct optional_move_assign_base; 544 #endif 545 546 template <class T> 547 struct optional_move_assign_base<T, false> : optional_copy_assign_base<T> { 548 using optional_copy_assign_base<T>::optional_copy_assign_base; 549 550 optional_move_assign_base() = default; 551 optional_move_assign_base(const optional_move_assign_base& rhs) = default; 552 553 optional_move_assign_base(optional_move_assign_base&& rhs) = default; 554 555 optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default; 556 operator =sol::detail::optional_move_assign_base557 optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept( 558 std::is_nothrow_move_constructible<T>::value&& std::is_nothrow_move_assignable<T>::value) { 559 this->assign(std::move(rhs)); 560 return *this; 561 } 562 }; 563 564 // optional_delete_ctor_base will conditionally delete copy and move 565 // constructors depending on whether T is copy/move constructible 566 template <class T, bool EnableCopy = std::is_copy_constructible<T>::value, bool EnableMove = std::is_move_constructible<T>::value> 567 struct optional_delete_ctor_base { 568 optional_delete_ctor_base() = default; 569 optional_delete_ctor_base(const optional_delete_ctor_base&) = default; 570 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; 571 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; 572 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; 573 }; 574 575 template <class T> 576 struct optional_delete_ctor_base<T, true, false> { 577 optional_delete_ctor_base() = default; 578 optional_delete_ctor_base(const optional_delete_ctor_base&) = default; 579 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; 580 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; 581 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; 582 }; 583 584 template <class T> 585 struct optional_delete_ctor_base<T, false, true> { 586 optional_delete_ctor_base() = default; 587 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; 588 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; 589 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; 590 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; 591 }; 592 593 template <class T> 594 struct optional_delete_ctor_base<T, false, false> { 595 optional_delete_ctor_base() = default; 596 optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; 597 optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; 598 optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; 599 optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; 600 }; 601 602 // optional_delete_assign_base will conditionally delete copy and move 603 // constructors depending on whether T is copy/move constructible + assignable 604 template <class T, bool EnableCopy = (std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value), 605 bool EnableMove = (std::is_move_constructible<T>::value && std::is_move_assignable<T>::value)> 606 struct optional_delete_assign_base { 607 optional_delete_assign_base() = default; 608 optional_delete_assign_base(const optional_delete_assign_base&) = default; 609 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; 610 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; 611 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; 612 }; 613 614 template <class T> 615 struct optional_delete_assign_base<T, true, false> { 616 optional_delete_assign_base() = default; 617 optional_delete_assign_base(const optional_delete_assign_base&) = default; 618 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; 619 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; 620 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; 621 }; 622 623 template <class T> 624 struct optional_delete_assign_base<T, false, true> { 625 optional_delete_assign_base() = default; 626 optional_delete_assign_base(const optional_delete_assign_base&) = default; 627 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; 628 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; 629 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; 630 }; 631 632 template <class T> 633 struct optional_delete_assign_base<T, false, false> { 634 optional_delete_assign_base() = default; 635 optional_delete_assign_base(const optional_delete_assign_base&) = default; 636 optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; 637 optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; 638 optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; 639 }; 640 641 } // namespace detail 642 643 /// \brief A tag type to represent an empty optional 644 using nullopt_t = std::nullopt_t; 645 646 /// \brief Represents an empty optional 647 /// \synopsis static constexpr nullopt_t nullopt; 648 /// 649 /// *Examples*: 650 /// ``` 651 /// sol::optional<int> a = sol::nullopt; 652 /// void foo (sol::optional<int>); 653 /// foo(sol::nullopt); //pass an empty optional 654 /// ``` 655 using std::nullopt; 656 657 /// @brief An exception for when an optional is accessed through specific methods while it is not engaged. 658 class bad_optional_access : public std::exception { 659 public: 660 /// @brief Default-constructs an optional exception. 661 bad_optional_access() = default; 662 /// @brief Returns a pointer to a null-terminated string containing the reason for the exception. what() const663 const char* what() const noexcept override { 664 return "Optional has no value"; 665 } 666 }; 667 668 /// An optional object is an object that contains the storage for another 669 /// object and manages the lifetime of this contained object, if any. The 670 /// contained object may be initialized after the optional object has been 671 /// initialized, and may be destroyed before the optional object has been 672 /// destroyed. The initialization state of the contained object is tracked by 673 /// the optional object. 674 template <class T> 675 class optional : private detail::optional_move_assign_base<T>, 676 private detail::optional_delete_ctor_base<T>, 677 private detail::optional_delete_assign_base<T> { 678 using base = detail::optional_move_assign_base<T>; 679 680 static_assert(!std::is_same<T, in_place_t>::value, "instantiation of optional with in_place_t is ill-formed"); 681 static_assert(!std::is_same<detail::decay_t<T>, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed"); 682 683 public: 684 // The different versions for C++14 and 11 are needed because deduced return 685 // types are not SFINAE-safe. This provides better support for things like 686 // generic lambdas. C.f. 687 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html 688 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 689 /// \group and_then 690 /// Carries out some operation which returns an optional on the stored 691 /// object if there is one. \requires `std::invoke(std::forward<F>(f), 692 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be 693 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a 694 /// `std::optional<U>`. The return value is empty if `*this` is empty, 695 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` 696 /// is returned. 697 /// \group and_then 698 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &; 699 template <class F> and_then(F && f)700 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { 701 using result = detail::invoke_result_t<F, T&>; 702 static_assert(detail::is_optional<result>::value, "F must return an optional"); 703 704 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 705 } 706 707 /// \group and_then 708 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&; 709 template <class F> and_then(F && f)710 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { 711 using result = detail::invoke_result_t<F, T&&>; 712 static_assert(detail::is_optional<result>::value, "F must return an optional"); 713 714 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); 715 } 716 717 /// \group and_then 718 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &; 719 template <class F> and_then(F && f) const720 constexpr auto and_then(F&& f) const& { 721 using result = detail::invoke_result_t<F, const T&>; 722 static_assert(detail::is_optional<result>::value, "F must return an optional"); 723 724 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 725 } 726 727 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 728 /// \group and_then 729 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&; 730 template <class F> and_then(F && f) const731 constexpr auto and_then(F&& f) const&& { 732 using result = detail::invoke_result_t<F, const T&&>; 733 static_assert(detail::is_optional<result>::value, "F must return an optional"); 734 735 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); 736 } 737 #endif 738 #else 739 /// \group and_then 740 /// Carries out some operation which returns an optional on the stored 741 /// object if there is one. \requires `std::invoke(std::forward<F>(f), 742 /// value())` returns a `std::optional<U>` for some `U`. 743 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), 744 /// value())`. Returns a `std::optional<U>`. The return value is empty if 745 /// `*this` is empty, otherwise the return value of 746 /// `std::invoke(std::forward<F>(f), value())` is returned. 747 /// \group and_then 748 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &; 749 template <class F> 750 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & { 751 using result = detail::invoke_result_t<F, T&>; 752 static_assert(detail::is_optional<result>::value, "F must return an optional"); 753 754 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 755 } 756 757 /// \group and_then 758 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&; 759 template <class F> 760 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&&> and_then(F&& f) && { 761 using result = detail::invoke_result_t<F, T&&>; 762 static_assert(detail::is_optional<result>::value, "F must return an optional"); 763 764 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); 765 } 766 767 /// \group and_then 768 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &; 769 template <class F> 770 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& { 771 using result = detail::invoke_result_t<F, const T&>; 772 static_assert(detail::is_optional<result>::value, "F must return an optional"); 773 774 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 775 } 776 777 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 778 /// \group and_then 779 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&; 780 template <class F> 781 constexpr detail::invoke_result_t<F, const T&&> and_then(F&& f) const&& { 782 using result = detail::invoke_result_t<F, const T&&>; 783 static_assert(detail::is_optional<result>::value, "F must return an optional"); 784 785 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : result(nullopt); 786 } 787 #endif 788 #endif 789 790 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 791 /// \brief Carries out some operation on the stored object if there is one. 792 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), 793 /// value())`. Returns a `std::optional<U>`. The return value is empty if 794 /// `*this` is empty, otherwise an `optional<U>` is constructed from the 795 /// return value of `std::invoke(std::forward<F>(f), value())` and is 796 /// returned. 797 /// 798 /// \group map 799 /// \synopsis template <class F> constexpr auto map(F &&f) &; 800 template <class F> map(F && f)801 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { 802 return optional_map_impl(*this, std::forward<F>(f)); 803 } 804 805 /// \group map 806 /// \synopsis template <class F> constexpr auto map(F &&f) &&; 807 template <class F> map(F && f)808 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { 809 return optional_map_impl(std::move(*this), std::forward<F>(f)); 810 } 811 812 /// \group map 813 /// \synopsis template <class F> constexpr auto map(F &&f) const&; 814 template <class F> map(F && f) const815 constexpr auto map(F&& f) const& { 816 return optional_map_impl(*this, std::forward<F>(f)); 817 } 818 819 /// \group map 820 /// \synopsis template <class F> constexpr auto map(F &&f) const&&; 821 template <class F> map(F && f) const822 constexpr auto map(F&& f) const&& { 823 return optional_map_impl(std::move(*this), std::forward<F>(f)); 824 } 825 #else 826 /// \brief Carries out some operation on the stored object if there is one. 827 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), 828 /// value())`. Returns a `std::optional<U>`. The return value is empty if 829 /// `*this` is empty, otherwise an `optional<U>` is constructed from the 830 /// return value of `std::invoke(std::forward<F>(f), value())` and is 831 /// returned. 832 /// 833 /// \group map 834 /// \synopsis template <class F> auto map(F &&f) &; 835 template <class F> optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())836 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & { 837 return optional_map_impl(*this, std::forward<F>(f)); 838 } 839 840 /// \group map 841 /// \synopsis template <class F> auto map(F &&f) &&; 842 template <class F> optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())843 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && { 844 return optional_map_impl(std::move(*this), std::forward<F>(f)); 845 } 846 847 /// \group map 848 /// \synopsis template <class F> auto map(F &&f) const&; 849 template <class F> optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())850 constexpr decltype(optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& { 851 return optional_map_impl(*this, std::forward<F>(f)); 852 } 853 854 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 855 /// \group map 856 /// \synopsis template <class F> auto map(F &&f) const&&; 857 template <class F> optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())858 constexpr decltype(optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& { 859 return optional_map_impl(std::move(*this), std::forward<F>(f)); 860 } 861 #endif 862 #endif 863 864 /// \brief Calls `f` if the optional is empty 865 /// \requires `std::invoke_result_t<F>` must be void or convertible to 866 /// `optional<T>`. 867 /// \effects If `*this` has a value, returns `*this`. 868 /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns 869 /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`. 870 /// 871 /// \group or_else 872 /// \synopsis template <class F> optional<T> or_else (F &&f) &; 873 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f)874 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { 875 if (has_value()) 876 return *this; 877 878 std::forward<F>(f)(); 879 return nullopt; 880 } 881 882 /// \exclude 883 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f)884 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { 885 return has_value() ? *this : std::forward<F>(f)(); 886 } 887 888 /// \group or_else 889 /// \synopsis template <class F> optional<T> or_else (F &&f) &&; 890 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f)891 optional<T> or_else(F&& f) && { 892 if (has_value()) 893 return std::move(*this); 894 895 std::forward<F>(f)(); 896 return nullopt; 897 } 898 899 /// \exclude 900 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f)901 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { 902 return has_value() ? std::move(*this) : std::forward<F>(f)(); 903 } 904 905 /// \group or_else 906 /// \synopsis template <class F> optional<T> or_else (F &&f) const &; 907 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f) const908 optional<T> or_else(F&& f) const& { 909 if (has_value()) 910 return *this; 911 912 std::forward<F>(f)(); 913 return nullopt; 914 } 915 916 /// \exclude 917 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f) const918 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { 919 return has_value() ? *this : std::forward<F>(f)(); 920 } 921 922 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 923 /// \exclude 924 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f) const925 optional<T> or_else(F&& f) const&& { 926 if (has_value()) 927 return std::move(*this); 928 929 std::forward<F>(f)(); 930 return nullopt; 931 } 932 933 /// \exclude 934 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f) const935 optional<T> or_else(F&& f) const&& { 936 return has_value() ? std::move(*this) : std::forward<F>(f)(); 937 } 938 #endif 939 940 /// \brief Maps the stored value with `f` if there is one, otherwise returns 941 /// `u`. 942 /// 943 /// \details If there is a value stored, then `f` is called with `**this` 944 /// and the value is returned. Otherwise `u` is returned. 945 /// 946 /// \group map_or 947 template <class F, class U> map_or(F && f,U && u)948 U map_or(F&& f, U&& u) & { 949 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); 950 } 951 952 /// \group map_or 953 template <class F, class U> map_or(F && f,U && u)954 U map_or(F&& f, U&& u) && { 955 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); 956 } 957 958 /// \group map_or 959 template <class F, class U> map_or(F && f,U && u) const960 U map_or(F&& f, U&& u) const& { 961 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); 962 } 963 964 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 965 /// \group map_or 966 template <class F, class U> map_or(F && f,U && u) const967 U map_or(F&& f, U&& u) const&& { 968 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); 969 } 970 #endif 971 972 /// \brief Maps the stored value with `f` if there is one, otherwise calls 973 /// `u` and returns the result. 974 /// 975 /// \details If there is a value stored, then `f` is 976 /// called with `**this` and the value is returned. Otherwise 977 /// `std::forward<U>(u)()` is returned. 978 /// 979 /// \group map_or_else 980 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &; 981 template <class F, class U> map_or_else(F && f,U && u)982 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & { 983 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); 984 } 985 986 /// \group map_or_else 987 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 988 /// &&; 989 template <class F, class U> map_or_else(F && f,U && u)990 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && { 991 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); 992 } 993 994 /// \group map_or_else 995 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 996 /// const &; 997 template <class F, class U> map_or_else(F && f,U && u) const998 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& { 999 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); 1000 } 1001 1002 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1003 /// \group map_or_else 1004 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 1005 /// const &&; 1006 template <class F, class U> map_or_else(F && f,U && u) const1007 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& { 1008 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); 1009 } 1010 #endif 1011 1012 /// \returns `u` if `*this` has a value, otherwise an empty optional. 1013 template <class U> conjunction(U && u) const1014 constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const { 1015 using result = optional<detail::decay_t<U>>; 1016 return has_value() ? result { u } : result { nullopt }; 1017 } 1018 1019 /// \returns `rhs` if `*this` is empty, otherwise the current value. 1020 /// \group disjunction disjunction(const optional & rhs)1021 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { 1022 return has_value() ? *this : rhs; 1023 } 1024 1025 /// \group disjunction disjunction(const optional & rhs) const1026 constexpr optional disjunction(const optional& rhs) const& { 1027 return has_value() ? *this : rhs; 1028 } 1029 1030 /// \group disjunction disjunction(const optional & rhs)1031 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { 1032 return has_value() ? std::move(*this) : rhs; 1033 } 1034 1035 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1036 /// \group disjunction disjunction(const optional & rhs) const1037 constexpr optional disjunction(const optional& rhs) const&& { 1038 return has_value() ? std::move(*this) : rhs; 1039 } 1040 #endif 1041 1042 /// \group disjunction disjunction(optional && rhs)1043 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { 1044 return has_value() ? *this : std::move(rhs); 1045 } 1046 1047 /// \group disjunction disjunction(optional && rhs) const1048 constexpr optional disjunction(optional&& rhs) const& { 1049 return has_value() ? *this : std::move(rhs); 1050 } 1051 1052 /// \group disjunction disjunction(optional && rhs)1053 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { 1054 return has_value() ? std::move(*this) : std::move(rhs); 1055 } 1056 1057 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1058 /// \group disjunction disjunction(optional && rhs) const1059 constexpr optional disjunction(optional&& rhs) const&& { 1060 return has_value() ? std::move(*this) : std::move(rhs); 1061 } 1062 #endif 1063 1064 /// Takes the value out of the optional, leaving it empty 1065 /// \group take take()1066 optional take() & { 1067 optional ret = *this; 1068 reset(); 1069 return ret; 1070 } 1071 1072 /// \group take take() const1073 optional take() const& { 1074 optional ret = *this; 1075 reset(); 1076 return ret; 1077 } 1078 1079 /// \group take take()1080 optional take() && { 1081 optional ret = std::move(*this); 1082 reset(); 1083 return ret; 1084 } 1085 1086 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1087 /// \group take take() const1088 optional take() const&& { 1089 optional ret = std::move(*this); 1090 reset(); 1091 return ret; 1092 } 1093 #endif 1094 1095 using value_type = T; 1096 1097 /// Constructs an optional that does not contain a value. 1098 /// \group ctor_empty 1099 constexpr optional() noexcept = default; 1100 1101 /// \group ctor_empty optional(nullopt_t)1102 constexpr optional(nullopt_t) noexcept { 1103 } 1104 1105 /// Copy constructor 1106 /// 1107 /// If `rhs` contains a value, the stored value is direct-initialized with 1108 /// it. Otherwise, the constructed optional is empty. 1109 SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default; 1110 1111 /// Move constructor 1112 /// 1113 /// If `rhs` contains a value, the stored value is direct-initialized with 1114 /// it. Otherwise, the constructed optional is empty. 1115 SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; 1116 1117 /// Constructs the stored value in-place using the given arguments. 1118 /// \group in_place 1119 /// \synopsis template <class... Args> constexpr explicit optional(in_place_t, Args&&... args); 1120 template <class... Args> optional(detail::enable_if_t<std::is_constructible<T,Args...>::value,in_place_t>,Args &&...args)1121 constexpr explicit optional(detail::enable_if_t<std::is_constructible<T, Args...>::value, in_place_t>, Args&&... args) 1122 : base(in_place, std::forward<Args>(args)...) { 1123 } 1124 1125 /// \group in_place 1126 /// \synopsis template <class U, class... Args>\nconstexpr explicit optional(in_place_t, std::initializer_list<U>&, Args&&... args); 1127 template <class U, class... Args> optional(detail::enable_if_t<std::is_constructible<T,std::initializer_list<U> &,Args &&...>::value,in_place_t>,std::initializer_list<U> il,Args &&...args)1128 SOL_TL_OPTIONAL_11_CONSTEXPR explicit optional(detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, in_place_t>, 1129 std::initializer_list<U> il, Args&&... args) { 1130 this->construct(il, std::forward<Args>(args)...); 1131 } 1132 1133 #if 0 // SOL_MODIFICATION 1134 /// Constructs the stored value with `u`. 1135 /// \synopsis template <class U=T> constexpr optional(U &&u); 1136 template <class U = T, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr> 1137 constexpr optional(U&& u) : base(in_place, std::forward<U>(u)) { 1138 } 1139 1140 /// \exclude 1141 template <class U = T, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr, detail::enable_forward_value<T, U>* = nullptr> 1142 constexpr explicit optional(U&& u) : base(in_place, std::forward<U>(u)) { 1143 } 1144 #else 1145 /// Constructs the stored value with `u`. 1146 /// \synopsis template <class U=T> constexpr optional(U &&u); optional(T && u)1147 constexpr optional(T&& u) : base(in_place, std::move(u)) { 1148 } 1149 1150 /// \exclude optional(const T & u)1151 constexpr optional(const T& u) : base(in_place, u) { 1152 } 1153 #endif // sol3 modification 1154 1155 /// Converting copy constructor. 1156 /// \synopsis template <class U> optional(const optional<U> &rhs); 1157 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<std::is_convertible<const U&, T>::value>* = nullptr> optional(const optional<U> & rhs)1158 optional(const optional<U>& rhs) { 1159 if (rhs.has_value()) { 1160 this->construct(*rhs); 1161 } 1162 } 1163 1164 /// \exclude 1165 template <class U, detail::enable_from_other<T, U, const U&>* = nullptr, detail::enable_if_t<!std::is_convertible<const U&, T>::value>* = nullptr> optional(const optional<U> & rhs)1166 explicit optional(const optional<U>& rhs) { 1167 if (rhs.has_value()) { 1168 this->construct(*rhs); 1169 } 1170 } 1171 1172 /// Converting move constructor. 1173 /// \synopsis template <class U> optional(optional<U> &&rhs); 1174 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<std::is_convertible<U&&, T>::value>* = nullptr> optional(optional<U> && rhs)1175 optional(optional<U>&& rhs) { 1176 if (rhs.has_value()) { 1177 this->construct(std::move(*rhs)); 1178 } 1179 } 1180 1181 /// \exclude 1182 template <class U, detail::enable_from_other<T, U, U&&>* = nullptr, detail::enable_if_t<!std::is_convertible<U&&, T>::value>* = nullptr> optional(optional<U> && rhs)1183 explicit optional(optional<U>&& rhs) { 1184 this->construct(std::move(*rhs)); 1185 } 1186 1187 /// Destroys the stored value if there is one. 1188 ~optional() = default; 1189 1190 /// Assignment to empty. 1191 /// 1192 /// Destroys the current value if there is one. operator =(nullopt_t)1193 optional& operator=(nullopt_t) noexcept { 1194 if (has_value()) { 1195 this->m_value.~T(); 1196 this->m_has_value = false; 1197 } 1198 1199 return *this; 1200 } 1201 1202 /// Copy assignment. 1203 /// 1204 /// Copies the value from `rhs` if there is one. Otherwise resets the stored 1205 /// value in `*this`. 1206 optional& operator=(const optional& rhs) = default; 1207 1208 /// Move assignment. 1209 /// 1210 /// Moves the value from `rhs` if there is one. Otherwise resets the stored 1211 /// value in `*this`. 1212 optional& operator=(optional&& rhs) = default; 1213 1214 /// Assigns the stored value from `u`, destroying the old value if there was 1215 /// one. 1216 /// \synopsis optional &operator=(U &&u); 1217 template <class U = T, detail::enable_assign_forward<T, U>* = nullptr> operator =(U && u)1218 optional& operator=(U&& u) { 1219 if (has_value()) { 1220 this->m_value = std::forward<U>(u); 1221 } 1222 else { 1223 this->construct(std::forward<U>(u)); 1224 } 1225 1226 return *this; 1227 } 1228 1229 /// Converting copy assignment operator. 1230 /// 1231 /// Copies the value from `rhs` if there is one. Otherwise resets the stored 1232 /// value in `*this`. 1233 /// \synopsis optional &operator=(const optional<U> & rhs); 1234 template <class U, detail::enable_assign_from_other<T, U, const U&>* = nullptr> operator =(const optional<U> & rhs)1235 optional& operator=(const optional<U>& rhs) { 1236 if (has_value()) { 1237 if (rhs.has_value()) { 1238 this->m_value = *rhs; 1239 } 1240 else { 1241 this->hard_reset(); 1242 } 1243 } 1244 1245 if (rhs.has_value()) { 1246 this->construct(*rhs); 1247 } 1248 1249 return *this; 1250 } 1251 1252 // TODO check exception guarantee 1253 /// Converting move assignment operator. 1254 /// 1255 /// Moves the value from `rhs` if there is one. Otherwise resets the stored 1256 /// value in `*this`. 1257 /// \synopsis optional &operator=(optional<U> && rhs); 1258 template <class U, detail::enable_assign_from_other<T, U, U>* = nullptr> operator =(optional<U> && rhs)1259 optional& operator=(optional<U>&& rhs) { 1260 if (has_value()) { 1261 if (rhs.has_value()) { 1262 this->m_value = std::move(*rhs); 1263 } 1264 else { 1265 this->hard_reset(); 1266 } 1267 } 1268 1269 if (rhs.has_value()) { 1270 this->construct(std::move(*rhs)); 1271 } 1272 1273 return *this; 1274 } 1275 1276 /// Constructs the value in-place, destroying the current one if there is 1277 /// one. 1278 /// \group emplace 1279 template <class... Args> emplace(Args &&...args)1280 T& emplace(Args&&... args) { 1281 static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args"); 1282 1283 *this = nullopt; 1284 this->construct(std::forward<Args>(args)...); 1285 return value(); 1286 } 1287 1288 /// \group emplace 1289 /// \synopsis template <class U, class... Args>\nT& emplace(std::initializer_list<U> il, Args &&... args); 1290 template <class U, class... Args> emplace(std::initializer_list<U> il,Args &&...args)1291 detail::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, T&> emplace(std::initializer_list<U> il, Args&&... args) { 1292 *this = nullopt; 1293 this->construct(il, std::forward<Args>(args)...); 1294 return value(); 1295 } 1296 1297 /// Swaps this optional with the other. 1298 /// 1299 /// If neither optionals have a value, nothing happens. 1300 /// If both have a value, the values are swapped. 1301 /// If one has a value, it is moved to the other and the movee is left 1302 /// valueless. swap(optional & rhs)1303 void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible<T>::value&& detail::is_nothrow_swappable<T>::value) { 1304 if (has_value()) { 1305 if (rhs.has_value()) { 1306 using std::swap; 1307 swap(**this, *rhs); 1308 } 1309 else { 1310 new (std::addressof(rhs.m_value)) T(std::move(this->m_value)); 1311 this->m_value.T::~T(); 1312 } 1313 } 1314 else if (rhs.has_value()) { 1315 new (std::addressof(this->m_value)) T(std::move(rhs.m_value)); 1316 rhs.m_value.T::~T(); 1317 } 1318 } 1319 1320 /// \returns a pointer to the stored value 1321 /// \requires a value is stored 1322 /// \group pointer 1323 /// \synopsis constexpr const T *operator->() const; operator ->() const1324 constexpr const T* operator->() const { 1325 return std::addressof(this->m_value); 1326 } 1327 1328 /// \group pointer 1329 /// \synopsis constexpr T *operator->(); operator ->()1330 SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { 1331 return std::addressof(this->m_value); 1332 } 1333 1334 /// \returns the stored value 1335 /// \requires a value is stored 1336 /// \group deref 1337 /// \synopsis constexpr T &operator*(); operator *()1338 SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() & { 1339 return this->m_value; 1340 } 1341 1342 /// \group deref 1343 /// \synopsis constexpr const T &operator*() const; operator *() const1344 constexpr const T& operator*() const& { 1345 return this->m_value; 1346 } 1347 1348 /// \exclude operator *()1349 SOL_TL_OPTIONAL_11_CONSTEXPR T&& operator*() && { 1350 return std::move(this->m_value); 1351 } 1352 1353 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1354 /// \exclude operator *() const1355 constexpr const T&& operator*() const&& { 1356 return std::move(this->m_value); 1357 } 1358 #endif 1359 1360 /// \returns whether or not the optional has a value 1361 /// \group has_value has_value() const1362 constexpr bool has_value() const noexcept { 1363 return this->m_has_value; 1364 } 1365 1366 /// \group has_value operator bool() const1367 constexpr explicit operator bool() const noexcept { 1368 return this->m_has_value; 1369 } 1370 1371 /// \returns the contained value if there is one, otherwise throws 1372 /// [bad_optional_access] 1373 /// \group value 1374 /// \synopsis constexpr T &value(); value()1375 SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & { 1376 if (has_value()) 1377 return this->m_value; 1378 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 1379 std::abort(); 1380 #else 1381 throw bad_optional_access(); 1382 #endif // No exceptions allowed 1383 } 1384 /// \group value 1385 /// \synopsis constexpr const T &value() const; value() const1386 SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& { 1387 if (has_value()) 1388 return this->m_value; 1389 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 1390 std::abort(); 1391 #else 1392 throw bad_optional_access(); 1393 #endif // No exceptions allowed 1394 } 1395 /// \exclude value()1396 SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && { 1397 if (has_value()) 1398 return std::move(this->m_value); 1399 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 1400 std::abort(); 1401 #else 1402 throw bad_optional_access(); 1403 #endif // No exceptions allowed 1404 } 1405 1406 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1407 /// \exclude value() const1408 SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& { 1409 if (has_value()) 1410 return std::move(this->m_value); 1411 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 1412 std::abort(); 1413 #else 1414 throw bad_optional_access(); 1415 #endif // No exceptions allowed 1416 } 1417 #endif 1418 1419 /// \returns the stored value if there is one, otherwise returns `u` 1420 /// \group value_or 1421 template <class U> value_or(U && u) const1422 constexpr T value_or(U&& u) const& { 1423 static_assert(std::is_copy_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be copy constructible and convertible from U"); 1424 return has_value() ? **this : static_cast<T>(std::forward<U>(u)); 1425 } 1426 1427 /// \group value_or 1428 template <class U> value_or(U && u)1429 SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && { 1430 static_assert(std::is_move_constructible<T>::value && std::is_convertible<U&&, T>::value, "T must be move constructible and convertible from U"); 1431 return has_value() ? **this : static_cast<T>(std::forward<U>(u)); 1432 } 1433 1434 /// Destroys the stored value if one exists, making the optional empty reset()1435 void reset() noexcept { 1436 if (has_value()) { 1437 this->m_value.~T(); 1438 this->m_has_value = false; 1439 } 1440 } 1441 }; // namespace sol 1442 1443 /// \group relop 1444 /// \brief Compares two optional objects 1445 /// \details If both optionals contain a value, they are compared with `T`s 1446 /// relational operators. Otherwise `lhs` and `rhs` are equal only if they are 1447 /// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs` 1448 /// is not. 1449 template <class T, class U> operator ==(const optional<T> & lhs,const optional<U> & rhs)1450 inline constexpr bool operator==(const optional<T>& lhs, const optional<U>& rhs) { 1451 return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs); 1452 } 1453 /// \group relop 1454 template <class T, class U> operator !=(const optional<T> & lhs,const optional<U> & rhs)1455 inline constexpr bool operator!=(const optional<T>& lhs, const optional<U>& rhs) { 1456 return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs); 1457 } 1458 /// \group relop 1459 template <class T, class U> operator <(const optional<T> & lhs,const optional<U> & rhs)1460 inline constexpr bool operator<(const optional<T>& lhs, const optional<U>& rhs) { 1461 return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); 1462 } 1463 /// \group relop 1464 template <class T, class U> operator >(const optional<T> & lhs,const optional<U> & rhs)1465 inline constexpr bool operator>(const optional<T>& lhs, const optional<U>& rhs) { 1466 return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); 1467 } 1468 /// \group relop 1469 template <class T, class U> operator <=(const optional<T> & lhs,const optional<U> & rhs)1470 inline constexpr bool operator<=(const optional<T>& lhs, const optional<U>& rhs) { 1471 return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); 1472 } 1473 /// \group relop 1474 template <class T, class U> operator >=(const optional<T> & lhs,const optional<U> & rhs)1475 inline constexpr bool operator>=(const optional<T>& lhs, const optional<U>& rhs) { 1476 return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); 1477 } 1478 1479 /// \group relop_nullopt 1480 /// \brief Compares an optional to a `nullopt` 1481 /// \details Equivalent to comparing the optional to an empty optional 1482 template <class T> operator ==(const optional<T> & lhs,nullopt_t)1483 inline constexpr bool operator==(const optional<T>& lhs, nullopt_t) noexcept { 1484 return !lhs.has_value(); 1485 } 1486 /// \group relop_nullopt 1487 template <class T> operator ==(nullopt_t,const optional<T> & rhs)1488 inline constexpr bool operator==(nullopt_t, const optional<T>& rhs) noexcept { 1489 return !rhs.has_value(); 1490 } 1491 /// \group relop_nullopt 1492 template <class T> operator !=(const optional<T> & lhs,nullopt_t)1493 inline constexpr bool operator!=(const optional<T>& lhs, nullopt_t) noexcept { 1494 return lhs.has_value(); 1495 } 1496 /// \group relop_nullopt 1497 template <class T> operator !=(nullopt_t,const optional<T> & rhs)1498 inline constexpr bool operator!=(nullopt_t, const optional<T>& rhs) noexcept { 1499 return rhs.has_value(); 1500 } 1501 /// \group relop_nullopt 1502 template <class T> operator <(const optional<T> &,nullopt_t)1503 inline constexpr bool operator<(const optional<T>&, nullopt_t) noexcept { 1504 return false; 1505 } 1506 /// \group relop_nullopt 1507 template <class T> operator <(nullopt_t,const optional<T> & rhs)1508 inline constexpr bool operator<(nullopt_t, const optional<T>& rhs) noexcept { 1509 return rhs.has_value(); 1510 } 1511 /// \group relop_nullopt 1512 template <class T> operator <=(const optional<T> & lhs,nullopt_t)1513 inline constexpr bool operator<=(const optional<T>& lhs, nullopt_t) noexcept { 1514 return !lhs.has_value(); 1515 } 1516 /// \group relop_nullopt 1517 template <class T> operator <=(nullopt_t,const optional<T> &)1518 inline constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept { 1519 return true; 1520 } 1521 /// \group relop_nullopt 1522 template <class T> operator >(const optional<T> & lhs,nullopt_t)1523 inline constexpr bool operator>(const optional<T>& lhs, nullopt_t) noexcept { 1524 return lhs.has_value(); 1525 } 1526 /// \group relop_nullopt 1527 template <class T> operator >(nullopt_t,const optional<T> &)1528 inline constexpr bool operator>(nullopt_t, const optional<T>&) noexcept { 1529 return false; 1530 } 1531 /// \group relop_nullopt 1532 template <class T> operator >=(const optional<T> &,nullopt_t)1533 inline constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept { 1534 return true; 1535 } 1536 /// \group relop_nullopt 1537 template <class T> operator >=(nullopt_t,const optional<T> & rhs)1538 inline constexpr bool operator>=(nullopt_t, const optional<T>& rhs) noexcept { 1539 return !rhs.has_value(); 1540 } 1541 1542 /// \group relop_t 1543 /// \brief Compares the optional with a value. 1544 /// \details If the optional has a value, it is compared with the other value 1545 /// using `T`s relational operators. Otherwise, the optional is considered 1546 /// less than the value. 1547 template <class T, class U> operator ==(const optional<T> & lhs,const U & rhs)1548 inline constexpr bool operator==(const optional<T>& lhs, const U& rhs) { 1549 return lhs.has_value() ? *lhs == rhs : false; 1550 } 1551 /// \group relop_t 1552 template <class T, class U> operator ==(const U & lhs,const optional<T> & rhs)1553 inline constexpr bool operator==(const U& lhs, const optional<T>& rhs) { 1554 return rhs.has_value() ? lhs == *rhs : false; 1555 } 1556 /// \group relop_t 1557 template <class T, class U> operator !=(const optional<T> & lhs,const U & rhs)1558 inline constexpr bool operator!=(const optional<T>& lhs, const U& rhs) { 1559 return lhs.has_value() ? *lhs != rhs : true; 1560 } 1561 /// \group relop_t 1562 template <class T, class U> operator !=(const U & lhs,const optional<T> & rhs)1563 inline constexpr bool operator!=(const U& lhs, const optional<T>& rhs) { 1564 return rhs.has_value() ? lhs != *rhs : true; 1565 } 1566 /// \group relop_t 1567 template <class T, class U> operator <(const optional<T> & lhs,const U & rhs)1568 inline constexpr bool operator<(const optional<T>& lhs, const U& rhs) { 1569 return lhs.has_value() ? *lhs < rhs : true; 1570 } 1571 /// \group relop_t 1572 template <class T, class U> operator <(const U & lhs,const optional<T> & rhs)1573 inline constexpr bool operator<(const U& lhs, const optional<T>& rhs) { 1574 return rhs.has_value() ? lhs < *rhs : false; 1575 } 1576 /// \group relop_t 1577 template <class T, class U> operator <=(const optional<T> & lhs,const U & rhs)1578 inline constexpr bool operator<=(const optional<T>& lhs, const U& rhs) { 1579 return lhs.has_value() ? *lhs <= rhs : true; 1580 } 1581 /// \group relop_t 1582 template <class T, class U> operator <=(const U & lhs,const optional<T> & rhs)1583 inline constexpr bool operator<=(const U& lhs, const optional<T>& rhs) { 1584 return rhs.has_value() ? lhs <= *rhs : false; 1585 } 1586 /// \group relop_t 1587 template <class T, class U> operator >(const optional<T> & lhs,const U & rhs)1588 inline constexpr bool operator>(const optional<T>& lhs, const U& rhs) { 1589 return lhs.has_value() ? *lhs > rhs : false; 1590 } 1591 /// \group relop_t 1592 template <class T, class U> operator >(const U & lhs,const optional<T> & rhs)1593 inline constexpr bool operator>(const U& lhs, const optional<T>& rhs) { 1594 return rhs.has_value() ? lhs > *rhs : true; 1595 } 1596 /// \group relop_t 1597 template <class T, class U> operator >=(const optional<T> & lhs,const U & rhs)1598 inline constexpr bool operator>=(const optional<T>& lhs, const U& rhs) { 1599 return lhs.has_value() ? *lhs >= rhs : false; 1600 } 1601 /// \group relop_t 1602 template <class T, class U> operator >=(const U & lhs,const optional<T> & rhs)1603 inline constexpr bool operator>=(const U& lhs, const optional<T>& rhs) { 1604 return rhs.has_value() ? lhs >= *rhs : true; 1605 } 1606 1607 /// \synopsis template <class T>\nvoid swap(optional<T> &lhs, optional<T> &rhs); 1608 template <class T, detail::enable_if_t<std::is_move_constructible<T>::value>* = nullptr, detail::enable_if_t<detail::is_swappable<T>::value>* = nullptr> swap(optional<T> & lhs,optional<T> & rhs)1609 void swap(optional<T>& lhs, optional<T>& rhs) noexcept(noexcept(lhs.swap(rhs))) { 1610 return lhs.swap(rhs); 1611 } 1612 1613 namespace detail { 1614 struct i_am_secret { }; 1615 } // namespace detail 1616 1617 template <class T = detail::i_am_secret, class U, class Ret = detail::conditional_t<std::is_same<T, detail::i_am_secret>::value, detail::decay_t<U>, T>> make_optional(U && v)1618 inline constexpr optional<Ret> make_optional(U&& v) { 1619 return optional<Ret>(std::forward<U>(v)); 1620 } 1621 1622 template <class T, class... Args> make_optional(Args &&...args)1623 inline constexpr optional<T> make_optional(Args&&... args) { 1624 return optional<T>(in_place, std::forward<Args>(args)...); 1625 } 1626 template <class T, class U, class... Args> make_optional(std::initializer_list<U> il,Args &&...args)1627 inline constexpr optional<T> make_optional(std::initializer_list<U> il, Args&&... args) { 1628 return optional<T>(in_place, il, std::forward<Args>(args)...); 1629 } 1630 1631 #if __cplusplus >= 201703L 1632 template <class T> 1633 optional(T) -> optional<T>; 1634 #endif 1635 1636 /// \exclude 1637 namespace detail { 1638 #ifdef SOL_TL_OPTIONAL_CXX14 1639 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), 1640 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr> optional_map_impl(Opt && opt,F && f)1641 constexpr auto optional_map_impl(Opt&& opt, F&& f) { 1642 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt); 1643 } 1644 1645 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), 1646 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr> optional_map_impl(Opt && opt,F && f)1647 auto optional_map_impl(Opt&& opt, F&& f) { 1648 if (opt.has_value()) { 1649 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)); 1650 return make_optional(monostate {}); 1651 } 1652 1653 return optional<monostate>(nullopt); 1654 } 1655 #else 1656 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), 1657 detail::enable_if_t<!std::is_void<Ret>::value>* = nullptr> 1658 1659 constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional<Ret> { 1660 return opt.has_value() ? detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)) : optional<Ret>(nullopt); 1661 } 1662 1663 template <class Opt, class F, class Ret = decltype(detail::invoke(std::declval<F>(), *std::declval<Opt>())), 1664 detail::enable_if_t<std::is_void<Ret>::value>* = nullptr> 1665 1666 auto optional_map_impl(Opt&& opt, F&& f) -> optional<monostate> { 1667 if (opt.has_value()) { 1668 detail::invoke(std::forward<F>(f), *std::forward<Opt>(opt)); 1669 return monostate {}; 1670 } 1671 1672 return nullopt; 1673 } 1674 #endif 1675 } // namespace detail 1676 1677 /// Specialization for when `T` is a reference. `optional<T&>` acts similarly 1678 /// to a `T*`, but provides more operations and shows intent more clearly. 1679 /// 1680 /// *Examples*: 1681 /// 1682 /// ``` 1683 /// int i = 42; 1684 /// sol::optional<int&> o = i; 1685 /// *o == 42; //true 1686 /// i = 12; 1687 /// *o = 12; //true 1688 /// &*o == &i; //true 1689 /// ``` 1690 /// 1691 /// Assignment has rebind semantics rather than assign-through semantics: 1692 /// 1693 /// ``` 1694 /// int j = 8; 1695 /// o = j; 1696 /// 1697 /// &*o == &j; //true 1698 /// ``` 1699 template <class T> 1700 class optional<T&> { 1701 public: 1702 // The different versions for C++14 and 11 are needed because deduced return 1703 // types are not SFINAE-safe. This provides better support for things like 1704 // generic lambdas. C.f. 1705 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html 1706 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 1707 /// \group and_then 1708 /// Carries out some operation which returns an optional on the stored 1709 /// object if there is one. \requires `std::invoke(std::forward<F>(f), 1710 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be 1711 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a 1712 /// `std::optional<U>`. The return value is empty if `*this` is empty, 1713 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` 1714 /// is returned. 1715 /// \group and_then 1716 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &; 1717 template <class F> and_then(F && f)1718 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { 1719 using result = detail::invoke_result_t<F, T&>; 1720 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1721 1722 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1723 } 1724 1725 /// \group and_then 1726 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&; 1727 template <class F> and_then(F && f)1728 SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { 1729 using result = detail::invoke_result_t<F, T&>; 1730 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1731 1732 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1733 } 1734 1735 /// \group and_then 1736 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &; 1737 template <class F> and_then(F && f) const1738 constexpr auto and_then(F&& f) const& { 1739 using result = detail::invoke_result_t<F, const T&>; 1740 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1741 1742 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1743 } 1744 1745 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1746 /// \group and_then 1747 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&; 1748 template <class F> and_then(F && f) const1749 constexpr auto and_then(F&& f) const&& { 1750 using result = detail::invoke_result_t<F, const T&>; 1751 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1752 1753 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1754 } 1755 #endif 1756 #else 1757 /// \group and_then 1758 /// Carries out some operation which returns an optional on the stored 1759 /// object if there is one. \requires `std::invoke(std::forward<F>(f), 1760 /// value())` returns a `std::optional<U>` for some `U`. \returns Let `U` be 1761 /// the result of `std::invoke(std::forward<F>(f), value())`. Returns a 1762 /// `std::optional<U>`. The return value is empty if `*this` is empty, 1763 /// otherwise the return value of `std::invoke(std::forward<F>(f), value())` 1764 /// is returned. 1765 /// \group and_then 1766 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &; 1767 template <class F> 1768 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) & { 1769 using result = detail::invoke_result_t<F, T&>; 1770 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1771 1772 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1773 } 1774 1775 /// \group and_then 1776 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) &&; 1777 template <class F> 1778 SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t<F, T&> and_then(F&& f) && { 1779 using result = detail::invoke_result_t<F, T&>; 1780 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1781 1782 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1783 } 1784 1785 /// \group and_then 1786 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &; 1787 template <class F> 1788 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const& { 1789 using result = detail::invoke_result_t<F, const T&>; 1790 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1791 1792 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1793 } 1794 1795 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1796 /// \group and_then 1797 /// \synopsis template <class F>\nconstexpr auto and_then(F &&f) const &&; 1798 template <class F> 1799 constexpr detail::invoke_result_t<F, const T&> and_then(F&& f) const&& { 1800 using result = detail::invoke_result_t<F, const T&>; 1801 static_assert(detail::is_optional<result>::value, "F must return an optional"); 1802 1803 return has_value() ? detail::invoke(std::forward<F>(f), **this) : result(nullopt); 1804 } 1805 #endif 1806 #endif 1807 1808 #if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) 1809 /// \brief Carries out some operation on the stored object if there is one. 1810 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), 1811 /// value())`. Returns a `std::optional<U>`. The return value is empty if 1812 /// `*this` is empty, otherwise an `optional<U>` is constructed from the 1813 /// return value of `std::invoke(std::forward<F>(f), value())` and is 1814 /// returned. 1815 /// 1816 /// \group map 1817 /// \synopsis template <class F> constexpr auto map(F &&f) &; 1818 template <class F> map(F && f)1819 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { 1820 return detail::optional_map_impl(*this, std::forward<F>(f)); 1821 } 1822 1823 /// \group map 1824 /// \synopsis template <class F> constexpr auto map(F &&f) &&; 1825 template <class F> map(F && f)1826 SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { 1827 return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); 1828 } 1829 1830 /// \group map 1831 /// \synopsis template <class F> constexpr auto map(F &&f) const&; 1832 template <class F> map(F && f) const1833 constexpr auto map(F&& f) const& { 1834 return detail::optional_map_impl(*this, std::forward<F>(f)); 1835 } 1836 1837 /// \group map 1838 /// \synopsis template <class F> constexpr auto map(F &&f) const&&; 1839 template <class F> map(F && f) const1840 constexpr auto map(F&& f) const&& { 1841 return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); 1842 } 1843 #else 1844 /// \brief Carries out some operation on the stored object if there is one. 1845 /// \returns Let `U` be the result of `std::invoke(std::forward<F>(f), 1846 /// value())`. Returns a `std::optional<U>`. The return value is empty if 1847 /// `*this` is empty, otherwise an `optional<U>` is constructed from the 1848 /// return value of `std::invoke(std::forward<F>(f), value())` and is 1849 /// returned. 1850 /// 1851 /// \group map 1852 /// \synopsis template <class F> auto map(F &&f) &; 1853 template <class F> optional_map_impl(std::declval<optional &> (),std::declval<F &&> ())1854 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&>(), std::declval<F&&>())) map(F&& f) & { 1855 return detail::optional_map_impl(*this, std::forward<F>(f)); 1856 } 1857 1858 /// \group map 1859 /// \synopsis template <class F> auto map(F &&f) &&; 1860 template <class F> optional_map_impl(std::declval<optional &&> (),std::declval<F &&> ())1861 SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval<optional&&>(), std::declval<F&&>())) map(F&& f) && { 1862 return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); 1863 } 1864 1865 /// \group map 1866 /// \synopsis template <class F> auto map(F &&f) const&; 1867 template <class F> optional_map_impl(std::declval<const optional &> (),std::declval<F &&> ())1868 constexpr decltype(detail::optional_map_impl(std::declval<const optional&>(), std::declval<F&&>())) map(F&& f) const& { 1869 return detail::optional_map_impl(*this, std::forward<F>(f)); 1870 } 1871 1872 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1873 /// \group map 1874 /// \synopsis template <class F> auto map(F &&f) const&&; 1875 template <class F> optional_map_impl(std::declval<const optional &&> (),std::declval<F &&> ())1876 constexpr decltype(detail::optional_map_impl(std::declval<const optional&&>(), std::declval<F&&>())) map(F&& f) const&& { 1877 return detail::optional_map_impl(std::move(*this), std::forward<F>(f)); 1878 } 1879 #endif 1880 #endif 1881 1882 /// \brief Calls `f` if the optional is empty 1883 /// \requires `std::invoke_result_t<F>` must be void or convertible to 1884 /// `optional<T>`. \effects If `*this` has a value, returns `*this`. 1885 /// Otherwise, if `f` returns `void`, calls `std::forward<F>(f)` and returns 1886 /// `std::nullopt`. Otherwise, returns `std::forward<F>(f)()`. 1887 /// 1888 /// \group or_else 1889 /// \synopsis template <class F> optional<T> or_else (F &&f) &; 1890 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f)1891 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { 1892 if (has_value()) 1893 return *this; 1894 1895 std::forward<F>(f)(); 1896 return nullopt; 1897 } 1898 1899 /// \exclude 1900 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f)1901 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { 1902 return has_value() ? *this : std::forward<F>(f)(); 1903 } 1904 1905 /// \group or_else 1906 /// \synopsis template <class F> optional<T> or_else (F &&f) &&; 1907 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f)1908 optional<T> or_else(F&& f) && { 1909 if (has_value()) 1910 return std::move(*this); 1911 1912 std::forward<F>(f)(); 1913 return nullopt; 1914 } 1915 1916 /// \exclude 1917 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f)1918 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { 1919 return has_value() ? std::move(*this) : std::forward<F>(f)(); 1920 } 1921 1922 /// \group or_else 1923 /// \synopsis template <class F> optional<T> or_else (F &&f) const &; 1924 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f) const1925 optional<T> or_else(F&& f) const& { 1926 if (has_value()) 1927 return *this; 1928 1929 std::forward<F>(f)(); 1930 return nullopt; 1931 } 1932 1933 /// \exclude 1934 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f) const1935 optional<T> SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { 1936 return has_value() ? *this : std::forward<F>(f)(); 1937 } 1938 1939 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1940 /// \exclude 1941 template <class F, detail::enable_if_ret_void<F>* = nullptr> or_else(F && f) const1942 optional<T> or_else(F&& f) const&& { 1943 if (has_value()) 1944 return std::move(*this); 1945 1946 std::forward<F>(f)(); 1947 return nullopt; 1948 } 1949 1950 /// \exclude 1951 template <class F, detail::disable_if_ret_void<F>* = nullptr> or_else(F && f) const1952 optional<T> or_else(F&& f) const&& { 1953 return has_value() ? std::move(*this) : std::forward<F>(f)(); 1954 } 1955 #endif 1956 1957 /// \brief Maps the stored value with `f` if there is one, otherwise returns 1958 /// `u`. 1959 /// 1960 /// \details If there is a value stored, then `f` is called with `**this` 1961 /// and the value is returned. Otherwise `u` is returned. 1962 /// 1963 /// \group map_or 1964 template <class F, class U> map_or(F && f,U && u)1965 U map_or(F&& f, U&& u) & { 1966 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); 1967 } 1968 1969 /// \group map_or 1970 template <class F, class U> map_or(F && f,U && u)1971 U map_or(F&& f, U&& u) && { 1972 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); 1973 } 1974 1975 /// \group map_or 1976 template <class F, class U> map_or(F && f,U && u) const1977 U map_or(F&& f, U&& u) const& { 1978 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u); 1979 } 1980 1981 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 1982 /// \group map_or 1983 template <class F, class U> map_or(F && f,U && u) const1984 U map_or(F&& f, U&& u) const&& { 1985 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u); 1986 } 1987 #endif 1988 1989 /// \brief Maps the stored value with `f` if there is one, otherwise calls 1990 /// `u` and returns the result. 1991 /// 1992 /// \details If there is a value stored, then `f` is 1993 /// called with `**this` and the value is returned. Otherwise 1994 /// `std::forward<U>(u)()` is returned. 1995 /// 1996 /// \group map_or_else 1997 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) &; 1998 template <class F, class U> map_or_else(F && f,U && u)1999 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) & { 2000 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); 2001 } 2002 2003 /// \group map_or_else 2004 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 2005 /// &&; 2006 template <class F, class U> map_or_else(F && f,U && u)2007 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) && { 2008 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); 2009 } 2010 2011 /// \group map_or_else 2012 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 2013 /// const &; 2014 template <class F, class U> map_or_else(F && f,U && u) const2015 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const& { 2016 return has_value() ? detail::invoke(std::forward<F>(f), **this) : std::forward<U>(u)(); 2017 } 2018 2019 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 2020 /// \group map_or_else 2021 /// \synopsis template <class F, class U>\nauto map_or_else(F &&f, U &&u) 2022 /// const &&; 2023 template <class F, class U> map_or_else(F && f,U && u) const2024 detail::invoke_result_t<U> map_or_else(F&& f, U&& u) const&& { 2025 return has_value() ? detail::invoke(std::forward<F>(f), std::move(**this)) : std::forward<U>(u)(); 2026 } 2027 #endif 2028 2029 /// \returns `u` if `*this` has a value, otherwise an empty optional. 2030 template <class U> conjunction(U && u) const2031 constexpr optional<typename std::decay<U>::type> conjunction(U&& u) const { 2032 using result = optional<detail::decay_t<U>>; 2033 return has_value() ? result { u } : result { nullopt }; 2034 } 2035 2036 /// \returns `rhs` if `*this` is empty, otherwise the current value. 2037 /// \group disjunction disjunction(const optional & rhs)2038 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { 2039 return has_value() ? *this : rhs; 2040 } 2041 2042 /// \group disjunction disjunction(const optional & rhs) const2043 constexpr optional disjunction(const optional& rhs) const& { 2044 return has_value() ? *this : rhs; 2045 } 2046 2047 /// \group disjunction disjunction(const optional & rhs)2048 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { 2049 return has_value() ? std::move(*this) : rhs; 2050 } 2051 2052 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 2053 /// \group disjunction disjunction(const optional & rhs) const2054 constexpr optional disjunction(const optional& rhs) const&& { 2055 return has_value() ? std::move(*this) : rhs; 2056 } 2057 #endif 2058 2059 /// \group disjunction disjunction(optional && rhs)2060 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { 2061 return has_value() ? *this : std::move(rhs); 2062 } 2063 2064 /// \group disjunction disjunction(optional && rhs) const2065 constexpr optional disjunction(optional&& rhs) const& { 2066 return has_value() ? *this : std::move(rhs); 2067 } 2068 2069 /// \group disjunction disjunction(optional && rhs)2070 SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { 2071 return has_value() ? std::move(*this) : std::move(rhs); 2072 } 2073 2074 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 2075 /// \group disjunction disjunction(optional && rhs) const2076 constexpr optional disjunction(optional&& rhs) const&& { 2077 return has_value() ? std::move(*this) : std::move(rhs); 2078 } 2079 #endif 2080 2081 /// Takes the value out of the optional, leaving it empty 2082 /// \group take take()2083 optional take() & { 2084 optional ret = *this; 2085 reset(); 2086 return ret; 2087 } 2088 2089 /// \group take take() const2090 optional take() const& { 2091 optional ret = *this; 2092 reset(); 2093 return ret; 2094 } 2095 2096 /// \group take take()2097 optional take() && { 2098 optional ret = std::move(*this); 2099 reset(); 2100 return ret; 2101 } 2102 2103 #ifndef SOL_TL_OPTIONAL_NO_CONSTRR 2104 /// \group take take() const2105 optional take() const&& { 2106 optional ret = std::move(*this); 2107 reset(); 2108 return ret; 2109 } 2110 #endif 2111 2112 using value_type = T&; 2113 2114 /// Constructs an optional that does not contain a value. 2115 /// \group ctor_empty optional()2116 constexpr optional() noexcept : m_value(nullptr) { 2117 } 2118 2119 /// \group ctor_empty optional(nullopt_t)2120 constexpr optional(nullopt_t) noexcept : m_value(nullptr) { 2121 } 2122 2123 /// Copy constructor 2124 /// 2125 /// If `rhs` contains a value, the stored value is direct-initialized with 2126 /// it. Otherwise, the constructed optional is empty. 2127 SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default; 2128 2129 /// Move constructor 2130 /// 2131 /// If `rhs` contains a value, the stored value is direct-initialized with 2132 /// it. Otherwise, the constructed optional is empty. 2133 SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; 2134 2135 /// Constructs the stored value with `u`. 2136 /// \synopsis template <class U=T> constexpr optional(U &&u); 2137 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr> optional(U && u)2138 constexpr optional(U&& u) : m_value(std::addressof(u)) { 2139 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue"); 2140 } 2141 2142 /// \exclude 2143 template <class U> optional(const optional<U> & rhs)2144 constexpr explicit optional(const optional<U>& rhs) : optional(*rhs) { 2145 } 2146 2147 /// No-op 2148 ~optional() = default; 2149 2150 /// Assignment to empty. 2151 /// 2152 /// Destroys the current value if there is one. operator =(nullopt_t)2153 optional& operator=(nullopt_t) noexcept { 2154 m_value = nullptr; 2155 return *this; 2156 } 2157 2158 /// Copy assignment. 2159 /// 2160 /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise 2161 /// resets the stored value in `*this`. 2162 optional& operator=(const optional& rhs) = default; 2163 2164 /// Rebinds this optional to `u`. 2165 /// 2166 /// \requires `U` must be an lvalue reference. 2167 /// \synopsis optional &operator=(U &&u); 2168 template <class U = T, detail::enable_if_t<!detail::is_optional<detail::decay_t<U>>::value>* = nullptr> operator =(U && u)2169 optional& operator=(U&& u) { 2170 static_assert(std::is_lvalue_reference<U>::value, "U must be an lvalue"); 2171 m_value = std::addressof(u); 2172 return *this; 2173 } 2174 2175 /// Converting copy assignment operator. 2176 /// 2177 /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise 2178 /// resets the stored value in `*this`. 2179 template <class U> operator =(const optional<U> & rhs)2180 optional& operator=(const optional<U>& rhs) { 2181 m_value = std::addressof(rhs.value()); 2182 return *this; 2183 } 2184 2185 /// Constructs the value in-place, destroying the current one if there is 2186 /// one. 2187 /// 2188 /// \group emplace 2189 template <class... Args> emplace(Args &&...args)2190 T& emplace(Args&&... args) noexcept { 2191 static_assert(std::is_constructible<T, Args&&...>::value, "T must be constructible with Args"); 2192 2193 *this = nullopt; 2194 this->construct(std::forward<Args>(args)...); 2195 } 2196 2197 /// Swaps this optional with the other. 2198 /// 2199 /// If neither optionals have a value, nothing happens. 2200 /// If both have a value, the values are swapped. 2201 /// If one has a value, it is moved to the other and the movee is left 2202 /// valueless. swap(optional & rhs)2203 void swap(optional& rhs) noexcept { 2204 std::swap(m_value, rhs.m_value); 2205 } 2206 2207 /// \returns a pointer to the stored value 2208 /// \requires a value is stored 2209 /// \group pointer 2210 /// \synopsis constexpr const T *operator->() const; operator ->() const2211 constexpr const T* operator->() const { 2212 return m_value; 2213 } 2214 2215 /// \group pointer 2216 /// \synopsis constexpr T *operator->(); operator ->()2217 SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { 2218 return m_value; 2219 } 2220 2221 /// \returns the stored value 2222 /// \requires a value is stored 2223 /// \group deref 2224 /// \synopsis constexpr T &operator*(); operator *()2225 SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() { 2226 return *m_value; 2227 } 2228 2229 /// \group deref 2230 /// \synopsis constexpr const T &operator*() const; operator *() const2231 constexpr const T& operator*() const { 2232 return *m_value; 2233 } 2234 2235 /// \returns whether or not the optional has a value 2236 /// \group has_value has_value() const2237 constexpr bool has_value() const noexcept { 2238 return m_value != nullptr; 2239 } 2240 2241 /// \group has_value operator bool() const2242 constexpr explicit operator bool() const noexcept { 2243 return m_value != nullptr; 2244 } 2245 2246 /// \returns the contained value if there is one, otherwise throws 2247 /// [bad_optional_access] 2248 /// \group value 2249 /// synopsis constexpr T &value(); value()2250 SOL_TL_OPTIONAL_11_CONSTEXPR T& value() { 2251 if (has_value()) 2252 return *m_value; 2253 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 2254 std::abort(); 2255 #else 2256 throw bad_optional_access(); 2257 #endif // No exceptions allowed 2258 } 2259 /// \group value 2260 /// \synopsis constexpr const T &value() const; value() const2261 SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const { 2262 if (has_value()) 2263 return *m_value; 2264 #if SOL_IS_OFF(SOL_EXCEPTIONS_I_) 2265 std::abort(); 2266 #else 2267 throw bad_optional_access(); 2268 #endif // No exceptions allowed 2269 } 2270 2271 /// \returns the stored value if there is one, otherwise returns `u` 2272 /// \group value_or 2273 template <class U> value_or(U && u) const2274 constexpr T& value_or(U&& u) const { 2275 static_assert(std::is_convertible<U&&, T&>::value, "T must be convertible from U"); 2276 return has_value() ? const_cast<T&>(**this) : static_cast<T&>(std::forward<U>(u)); 2277 } 2278 2279 /// Destroys the stored value if one exists, making the optional empty reset()2280 void reset() noexcept { 2281 m_value = nullptr; 2282 } 2283 2284 private: 2285 T* m_value; 2286 }; 2287 2288 } // namespace sol 2289 2290 namespace std { 2291 // TODO SFINAE 2292 template <class T> 2293 struct hash<::sol::optional<T>> { operator ()std::hash2294 ::std::size_t operator()(const ::sol::optional<T>& o) const { 2295 if (!o.has_value()) 2296 return 0; 2297 2298 return ::std::hash<::sol::detail::remove_const_t<T>>()(*o); 2299 } 2300 }; 2301 } // namespace std 2302 2303 #endif // SOL_TL_OPTIONAL_HPP 2304