From bd3fe0cac583739bc0d7c4b5c8f301bb350abca0 Mon Sep 17 00:00:00 2001 From: Andy Belle-Isle Date: Fri, 30 Aug 2019 00:19:31 -0400 Subject: Renamed lib to deps so github will ignore it for language stats --- lib/sol2/include/sol/optional_implementation.hpp | 2272 ---------------------- 1 file changed, 2272 deletions(-) delete mode 100644 lib/sol2/include/sol/optional_implementation.hpp (limited to 'lib/sol2/include/sol/optional_implementation.hpp') diff --git a/lib/sol2/include/sol/optional_implementation.hpp b/lib/sol2/include/sol/optional_implementation.hpp deleted file mode 100644 index 0d9abc0..0000000 --- a/lib/sol2/include/sol/optional_implementation.hpp +++ /dev/null @@ -1,2272 +0,0 @@ -// The MIT License (MIT) - -// Copyright (c) 2013-2019 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Taken from: TartanLlama/optional on Github, because -// holy shit am I done dealing with C++11 constexpr - -/// -// optional - An implementation of std::optional with extensions -// Written in 2017 by Simon Brand (@TartanLlama) -// -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to the -// public domain worldwide. This software is distributed without any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. If not, see -// . -/// - -#ifndef SOL_TL_OPTIONAL_HPP -#define SOL_TL_OPTIONAL_HPP - -#include "in_place.hpp" - -#define SOL_TL_OPTIONAL_VERSION_MAJOR 0 -#define SOL_TL_OPTIONAL_VERSION_MINOR 5 - -#include -#include -#include -#include -#include - -#if (defined(_MSC_VER) && _MSC_VER == 1900) -#define SOL_TL_OPTIONAL_MSVC2015 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) -#define SOL_TL_OPTIONAL_GCC49 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__)) -#define SOL_TL_OPTIONAL_GCC54 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__)) -#define SOL_TL_OPTIONAL_GCC55 -#endif - -#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__)) -// GCC < 5 doesn't support overloading on const&& for member functions -#define SOL_TL_OPTIONAL_NO_CONSTRR - -// GCC < 5 doesn't support some standard C++11 type traits -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor::value -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value - -// This one will be different for GCC 5.7 if it's ever supported -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value - -// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector -// for non-copyable types -#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__)) -#ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -#define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX -namespace sol { namespace detail { - template - struct is_trivially_copy_constructible : std::is_trivially_copy_constructible {}; -#ifdef _GLIBCXX_VECTOR - template - struct is_trivially_copy_constructible> : std::is_trivially_copy_constructible {}; -#endif -}} // namespace sol::detail -#endif - -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible::value -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value -#else -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible::value -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value -#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value -#endif - -#if __cplusplus > 201103L -#define SOL_TL_OPTIONAL_CXX14 -#endif - -// constexpr implies const in C++11, not C++14 -#if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49)) -/// \exclude -#define SOL_TL_OPTIONAL_11_CONSTEXPR -#else -/// \exclude -#define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr -#endif - -namespace sol { -#ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX -#define SOL_TL_MONOSTATE_INPLACE_MUTEX - /// \brief Used to represent an optional with no data; essentially a bool - class monostate {}; -#endif - - template - class optional; - - /// \exclude - namespace detail { -#ifndef SOL_TL_TRAITS_MUTEX -#define SOL_TL_TRAITS_MUTEX - // C++14-style aliases for brevity - template - using remove_const_t = typename std::remove_const::type; - template - using remove_reference_t = typename std::remove_reference::type; - template - using decay_t = typename std::decay::type; - template - using enable_if_t = typename std::enable_if::type; - template - using conditional_t = typename std::conditional::type; - - // std::conjunction from C++17 - template - struct conjunction : std::true_type {}; - template - struct conjunction : B {}; - template - struct conjunction : std::conditional, B>::type {}; - -#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L -#define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND -#endif - -// In C++11 mode, there's an issue in libc++'s std::mem_fn -// which results in a hard-error when using it in a noexcept expression -// in some cases. This is a check to workaround the common failing case. -#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND - template - struct is_pointer_to_non_const_member_func : std::false_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - template - struct is_pointer_to_non_const_member_func : std::true_type {}; - - template - struct is_const_or_const_ref : std::false_type {}; - template - struct is_const_or_const_ref : std::true_type {}; - template - struct is_const_or_const_ref : std::true_type {}; -#endif - - // std::invoke from C++17 - // https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround - template ::value && is_const_or_const_ref::value)>, -#endif - typename = enable_if_t>::value>, int = 0> - constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward(args)...))) - -> decltype(std::mem_fn(f)(std::forward(args)...)) { - return std::mem_fn(f)(std::forward(args)...); - } - - template >::value>> - constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) { - return std::forward(f)(std::forward(args)...); - } - - // std::invoke_result from C++17 - template - struct invoke_result_impl; - - template - struct invoke_result_impl(), std::declval()...), void()), Us...> { - using type = decltype(detail::invoke(std::declval(), std::declval()...)); - }; - - template - using invoke_result = invoke_result_impl; - - template - using invoke_result_t = typename invoke_result::type; -#endif - - // std::void_t from C++17 - template - struct voider { - using type = void; - }; - template - using void_t = typename voider::type; - - // Trait for checking if a type is a sol::optional - template - struct is_optional_impl : std::false_type {}; - template - struct is_optional_impl> : std::true_type {}; - template - using is_optional = is_optional_impl>; - - // Change void to sol::monostate - template - using fixup_void = conditional_t::value, monostate, U>; - - template > - using get_map_return = optional>>; - - // Check if invoking F for some Us returns void - template - struct returns_void_impl; - template - struct returns_void_impl>, U...> : std::is_void> {}; - template - using returns_void = returns_void_impl; - - template - using enable_if_ret_void = enable_if_t::value>; - - template - using disable_if_ret_void = enable_if_t::value>; - - template - using enable_forward_value = detail::enable_if_t::value && !std::is_same, in_place_t>::value - && !std::is_same, detail::decay_t>::value>; - - template - using enable_from_other = detail::enable_if_t::value && !std::is_constructible&>::value - && !std::is_constructible&&>::value && !std::is_constructible&>::value - && !std::is_constructible&&>::value && !std::is_convertible&, T>::value - && !std::is_convertible&&, T>::value && !std::is_convertible&, T>::value - && !std::is_convertible&&, T>::value>; - - template - using enable_assign_forward = detail::enable_if_t, detail::decay_t>::value - && !detail::conjunction, std::is_same>>::value && std::is_constructible::value - && std::is_assignable::value>; - - template - using enable_assign_from_other = detail::enable_if_t::value && std::is_assignable::value - && !std::is_constructible&>::value && !std::is_constructible&&>::value - && !std::is_constructible&>::value && !std::is_constructible&&>::value - && !std::is_convertible&, T>::value && !std::is_convertible&&, T>::value - && !std::is_convertible&, T>::value && !std::is_convertible&&, T>::value - && !std::is_assignable&>::value && !std::is_assignable&&>::value - && !std::is_assignable&>::value && !std::is_assignable&&>::value>; - -#ifdef _MSC_VER - // TODO make a version which works with MSVC - template - struct is_swappable : std::true_type {}; - - template - struct is_nothrow_swappable : std::true_type {}; -#else - // https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept - namespace swap_adl_tests { - // if swap ADL finds this then it would call std::swap otherwise (same - // signature) - struct tag {}; - - template - tag swap(T&, T&); - template - tag swap(T (&a)[N], T (&b)[N]); - - // helper functions to test if an unqualified swap is possible, and if it - // becomes std::swap - template - std::false_type can_swap(...) noexcept(false); - template (), std::declval()))> - std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), std::declval()))); - - template - std::false_type uses_std(...); - template - std::is_same(), std::declval())), tag> uses_std(int); - - template - struct is_std_swap_noexcept - : std::integral_constant::value && std::is_nothrow_move_assignable::value> {}; - - template - struct is_std_swap_noexcept : is_std_swap_noexcept {}; - - template - struct is_adl_swap_noexcept : std::integral_constant(0))> {}; - } // namespace swap_adl_tests - - template - struct is_swappable : std::integral_constant(0))::value - && (!decltype(detail::swap_adl_tests::uses_std(0))::value - || (std::is_move_assignable::value && std::is_move_constructible::value))> {}; - - template - struct is_swappable : std::integral_constant(0))::value - && (!decltype(detail::swap_adl_tests::uses_std(0))::value || is_swappable::value)> {}; - - template - struct is_nothrow_swappable - : std::integral_constant::value - && ((decltype(detail::swap_adl_tests::uses_std(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept::value) - || (!decltype(detail::swap_adl_tests::uses_std(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept::value))> {}; -#endif - - // The storage base manages the actual storage, and correctly propagates - // trivial destruction from T. This case is for when T is not trivially - // destructible. - template ::value> - struct optional_storage_base { - SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { - } - - template - SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward(u)...), m_has_value(true) { - } - - ~optional_storage_base() { - if (m_has_value) { - m_value.~T(); - m_has_value = false; - } - } - - struct dummy {}; - union { - dummy m_dummy; - T m_value; - }; - - bool m_has_value; - }; - - // This case is for when T is trivially destructible. - template - struct optional_storage_base { - SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) { - } - - template - SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward(u)...), m_has_value(true) { - } - - // No destructor, so this class is trivially destructible - - struct dummy {}; - union { - dummy m_dummy; - T m_value; - }; - - bool m_has_value = false; - }; - - // This base class provides some handy member functions which can be used in - // further derived classes - template - struct optional_operations_base : optional_storage_base { - using optional_storage_base::optional_storage_base; - - void hard_reset() noexcept { - get().~T(); - this->m_has_value = false; - } - - template - void construct(Args&&... args) noexcept { - new (std::addressof(this->m_value)) T(std::forward(args)...); - this->m_has_value = true; - } - - template - void assign(Opt&& rhs) { - if (this->has_value()) { - if (rhs.has_value()) { - this->m_value = std::forward(rhs).get(); - } - else { - this->m_value.~T(); - this->m_has_value = false; - } - } - - else if (rhs.has_value()) { - construct(std::forward(rhs).get()); - } - } - - bool has_value() const { - return this->m_has_value; - } - - SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & { - return this->m_value; - } - SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& { - return this->m_value; - } - SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && { - return std::move(this->m_value); - } -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - constexpr const T&& get() const&& { - return std::move(this->m_value); - } -#endif - }; - - // This class manages conditionally having a trivial copy constructor - // This specialization is for when T is trivially copy constructible - template - struct optional_copy_base : optional_operations_base { - using optional_operations_base::optional_operations_base; - }; - - // This specialization is for when T is not trivially copy constructible - template - struct optional_copy_base : optional_operations_base { - using optional_operations_base::optional_operations_base; - - optional_copy_base() = default; - optional_copy_base(const optional_copy_base& rhs) { - if (rhs.has_value()) { - this->construct(rhs.get()); - } - else { - this->m_has_value = false; - } - } - - optional_copy_base(optional_copy_base&& rhs) = default; - optional_copy_base& operator=(const optional_copy_base& rhs) = default; - optional_copy_base& operator=(optional_copy_base&& rhs) = default; - }; - -// This class manages conditionally having a trivial move constructor -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_constructible. We -// have to make do with a non-trivial move constructor even if T is trivially -// move constructible -#ifndef SOL_TL_OPTIONAL_GCC49 - template ::value> - struct optional_move_base : optional_copy_base { - using optional_copy_base::optional_copy_base; - }; -#else - template - struct optional_move_base; -#endif - template - struct optional_move_base : optional_copy_base { - using optional_copy_base::optional_copy_base; - - optional_move_base() = default; - optional_move_base(const optional_move_base& rhs) = default; - - optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible::value) { - if (rhs.has_value()) { - this->construct(std::move(rhs.get())); - } - else { - this->m_has_value = false; - } - } - optional_move_base& operator=(const optional_move_base& rhs) = default; - optional_move_base& operator=(optional_move_base&& rhs) = default; - }; - - // This class manages conditionally having a trivial copy assignment operator - template - struct optional_copy_assign_base : optional_move_base { - using optional_move_base::optional_move_base; - }; - - template - struct optional_copy_assign_base : optional_move_base { - using optional_move_base::optional_move_base; - - optional_copy_assign_base() = default; - optional_copy_assign_base(const optional_copy_assign_base& rhs) = default; - - optional_copy_assign_base(optional_copy_assign_base&& rhs) = default; - optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) { - this->assign(rhs); - return *this; - } - optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default; - }; - -// This class manages conditionally having a trivial move assignment operator -// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it -// doesn't implement an analogue to std::is_trivially_move_assignable. We have -// to make do with a non-trivial move assignment operator even if T is trivially -// move assignable -#ifndef SOL_TL_OPTIONAL_GCC49 - template ::value&& std::is_trivially_move_constructible::value&& std::is_trivially_move_assignable::value> - struct optional_move_assign_base : optional_copy_assign_base { - using optional_copy_assign_base::optional_copy_assign_base; - }; -#else - template - struct optional_move_assign_base; -#endif - - template - struct optional_move_assign_base : optional_copy_assign_base { - using optional_copy_assign_base::optional_copy_assign_base; - - optional_move_assign_base() = default; - optional_move_assign_base(const optional_move_assign_base& rhs) = default; - - optional_move_assign_base(optional_move_assign_base&& rhs) = default; - - optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default; - - optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept( - std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value) { - this->assign(std::move(rhs)); - return *this; - } - }; - - // optional_delete_ctor_base will conditionally delete copy and move - // constructors depending on whether T is copy/move constructible - template ::value, bool EnableMove = std::is_move_constructible::value> - struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; - }; - - template - struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; - }; - - template - struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; - }; - - template - struct optional_delete_ctor_base { - optional_delete_ctor_base() = default; - optional_delete_ctor_base(const optional_delete_ctor_base&) = delete; - optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete; - optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default; - optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default; - }; - - // optional_delete_assign_base will conditionally delete copy and move - // constructors depending on whether T is copy/move constructible + assignable - template ::value && std::is_copy_assignable::value), - bool EnableMove = (std::is_move_constructible::value && std::is_move_assignable::value)> - struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; - optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; - }; - - template - struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default; - optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; - }; - - template - struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; - optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default; - }; - - template - struct optional_delete_assign_base { - optional_delete_assign_base() = default; - optional_delete_assign_base(const optional_delete_assign_base&) = default; - optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default; - optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete; - optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete; - }; - - } // namespace detail - - /// \brief A tag type to represent an empty optional - struct nullopt_t { - struct do_not_use {}; - constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept { - } - }; - /// \brief Represents an empty optional - /// \synopsis static constexpr nullopt_t nullopt; - /// - /// *Examples*: - /// ``` - /// sol::optional a = sol::nullopt; - /// void foo (sol::optional); - /// foo(sol::nullopt); //pass an empty optional - /// ``` - static constexpr nullopt_t nullopt{ nullopt_t::do_not_use{}, nullopt_t::do_not_use{} }; - - class bad_optional_access : public std::exception { - public: - bad_optional_access() = default; - const char* what() const noexcept { - return "Optional has no value"; - } - }; - - /// An optional object is an object that contains the storage for another - /// object and manages the lifetime of this contained object, if any. The - /// contained object may be initialized after the optional object has been - /// initialized, and may be destroyed before the optional object has been - /// destroyed. The initialization state of the contained object is tracked by - /// the optional object. - template - class optional : private detail::optional_move_assign_base, - private detail::optional_delete_ctor_base, - private detail::optional_delete_assign_base { - using base = detail::optional_move_assign_base; - - static_assert(!std::is_same::value, "instantiation of optional with in_place_t is ill-formed"); - static_assert(!std::is_same, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed"); - - public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr auto and_then(F&& f) const& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr auto and_then(F&& f) const&& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); - } -#endif -#else - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise the return value of - /// `std::invoke(std::forward(f), value())` is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr detail::invoke_result_t and_then(F&& f) const& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr detail::invoke_result_t and_then(F&& f) const&& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : result(nullopt); - } -#endif -#endif - -#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&; - template - constexpr auto map(F&& f) const& { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&&; - template - constexpr auto map(F&& f) const&& { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template auto map(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), std::declval())) map(F&& f) & { - return optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR decltype(optional_map_impl(std::declval(), std::declval())) map(F&& f) && { - return optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) const&; - template - constexpr decltype(optional_map_impl(std::declval(), std::declval())) map(F&& f) const& { - return optional_map_impl(*this, std::forward(f)); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map - /// \synopsis template auto map(F &&f) const&&; - template - constexpr decltype(optional_map_impl(std::declval(), std::declval())) map(F&& f) const&& { - return optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// \brief Calls `f` if the optional is empty - /// \requires `std::invoke_result_t` must be void or convertible to - /// `optional`. - /// \effects If `*this` has a value, returns `*this`. - /// Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns - /// `std::nullopt`. Otherwise, returns `std::forward(f)()`. - /// - /// \group or_else - /// \synopsis template optional or_else (F &&f) &; - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { - return has_value() ? *this : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) &&; - template * = nullptr> - optional or_else(F&& f) && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) const &; - template * = nullptr> - optional or_else(F&& f) const& { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \exclude - template * = nullptr> - optional or_else(F&& f) const&& { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional or_else(F&& f) const&& { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise returns - /// `u`. - /// - /// \details If there is a value stored, then `f` is called with `**this` - /// and the value is returned. Otherwise `u` is returned. - /// - /// \group map_or - template - U map_or(F&& f, U&& u) & { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u); - } - - /// \group map_or - template - U map_or(F&& f, U&& u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u); - } - - /// \group map_or - template - U map_or(F&& f, U&& u) const& { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map_or - template - U map_or(F&& f, U&& u) const&& { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - /// - /// \details If there is a value stored, then `f` is - /// called with `**this` and the value is returned. Otherwise - /// `std::forward(u)()` is returned. - /// - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) &; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) & { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// &&; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const& { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u)(); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &&; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const&& { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u)(); - } -#endif - - /// \returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U&& u) const { - using result = optional>; - return has_value() ? result{ u } : result{ nullopt }; - } - - /// \returns `rhs` if `*this` is empty, otherwise the current value. - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - constexpr optional disjunction(const optional& rhs) const& { - return has_value() ? *this : rhs; - } - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(const optional& rhs) const&& { - return has_value() ? std::move(*this) : rhs; - } -#endif - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - constexpr optional disjunction(optional&& rhs) const& { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(optional&& rhs) const&& { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - /// \group take - optional take() & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() const& { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() && { - optional ret = std::move(*this); - reset(); - return ret; - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group take - optional take() const&& { - optional ret = std::move(*this); - reset(); - return ret; - } -#endif - - using value_type = T; - - /// Constructs an optional that does not contain a value. - /// \group ctor_empty - constexpr optional() noexcept = default; - - /// \group ctor_empty - constexpr optional(nullopt_t) noexcept { - } - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; - - /// Constructs the stored value in-place using the given arguments. - /// \group in_place - /// \synopsis template constexpr explicit optional(in_place_t, Args&&... args); - template - constexpr explicit optional(detail::enable_if_t::value, in_place_t>, Args&&... args) - : base(in_place, std::forward(args)...) { - } - - /// \group in_place - /// \synopsis template \nconstexpr explicit optional(in_place_t, std::initializer_list&, Args&&... args); - template - SOL_TL_OPTIONAL_11_CONSTEXPR explicit optional(detail::enable_if_t&, Args&&...>::value, in_place_t>, - std::initializer_list il, Args&&... args) { - this->construct(il, std::forward(args)...); - } - -#if 0 // SOL_MODIFICATION - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); - template ::value>* = nullptr, detail::enable_forward_value* = nullptr> - constexpr optional(U&& u) : base(in_place, std::forward(u)) { - } - - /// \exclude - template ::value>* = nullptr, detail::enable_forward_value* = nullptr> - constexpr explicit optional(U&& u) : base(in_place, std::forward(u)) { - } -#else - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); - constexpr optional(T&& u) : base(in_place, std::move(u)) { - } - - /// \exclude - constexpr optional(const T& u) : base(in_place, u) { - } -#endif // sol3 modification - - /// Converting copy constructor. - /// \synopsis template optional(const optional &rhs); - template * = nullptr, detail::enable_if_t::value>* = nullptr> - optional(const optional& rhs) { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - /// \exclude - template * = nullptr, detail::enable_if_t::value>* = nullptr> - explicit optional(const optional& rhs) { - if (rhs.has_value()) { - this->construct(*rhs); - } - } - - /// Converting move constructor. - /// \synopsis template optional(optional &&rhs); - template * = nullptr, detail::enable_if_t::value>* = nullptr> - optional(optional&& rhs) { - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - } - - /// \exclude - template * = nullptr, detail::enable_if_t::value>* = nullptr> - explicit optional(optional&& rhs) { - this->construct(std::move(*rhs)); - } - - /// Destroys the stored value if there is one. - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional& operator=(nullopt_t) noexcept { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - - return *this; - } - - /// Copy assignment. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional& operator=(const optional& rhs) = default; - - /// Move assignment. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - optional& operator=(optional&& rhs) = default; - - /// Assigns the stored value from `u`, destroying the old value if there was - /// one. - /// \synopsis optional &operator=(U &&u); - template * = nullptr> - optional& operator=(U&& u) { - if (has_value()) { - this->m_value = std::forward(u); - } - else { - this->construct(std::forward(u)); - } - - return *this; - } - - /// Converting copy assignment operator. - /// - /// Copies the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - /// \synopsis optional &operator=(const optional & rhs); - template * = nullptr> - optional& operator=(const optional& rhs) { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = *rhs; - } - else { - this->hard_reset(); - } - } - - if (rhs.has_value()) { - this->construct(*rhs); - } - - return *this; - } - - // TODO check exception guarantee - /// Converting move assignment operator. - /// - /// Moves the value from `rhs` if there is one. Otherwise resets the stored - /// value in `*this`. - /// \synopsis optional &operator=(optional && rhs); - template * = nullptr> - optional& operator=(optional&& rhs) { - if (has_value()) { - if (rhs.has_value()) { - this->m_value = std::move(*rhs); - } - else { - this->hard_reset(); - } - } - - if (rhs.has_value()) { - this->construct(std::move(*rhs)); - } - - return *this; - } - - /// Constructs the value in-place, destroying the current one if there is - /// one. - /// \group emplace - template - T& emplace(Args&&... args) { - static_assert(std::is_constructible::value, "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - return value(); - } - - /// \group emplace - /// \synopsis template \nT& emplace(std::initializer_list il, Args &&... args); - template - detail::enable_if_t&, Args&&...>::value, T&> emplace(std::initializer_list il, Args&&... args) { - *this = nullopt; - this->construct(il, std::forward(args)...); - return value(); - } - - /// Swaps this optional with the other. - /// - /// If neither optionals have a value, nothing happens. - /// If both have a value, the values are swapped. - /// If one has a value, it is moved to the other and the movee is left - /// valueless. - void swap(optional& rhs) noexcept(std::is_nothrow_move_constructible::value&& detail::is_nothrow_swappable::value) { - if (has_value()) { - if (rhs.has_value()) { - using std::swap; - swap(**this, *rhs); - } - else { - new (std::addressof(rhs.m_value)) T(std::move(this->m_value)); - this->m_value.T::~T(); - } - } - else if (rhs.has_value()) { - new (std::addressof(this->m_value)) T(std::move(rhs.m_value)); - rhs.m_value.T::~T(); - } - } - - /// \returns a pointer to the stored value - /// \requires a value is stored - /// \group pointer - /// \synopsis constexpr const T *operator->() const; - constexpr const T* operator->() const { - return std::addressof(this->m_value); - } - - /// \group pointer - /// \synopsis constexpr T *operator->(); - SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { - return std::addressof(this->m_value); - } - - /// \returns the stored value - /// \requires a value is stored - /// \group deref - /// \synopsis constexpr T &operator*(); - SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() & { - return this->m_value; - } - - /// \group deref - /// \synopsis constexpr const T &operator*() const; - constexpr const T& operator*() const& { - return this->m_value; - } - - /// \exclude - SOL_TL_OPTIONAL_11_CONSTEXPR T&& operator*() && { - return std::move(this->m_value); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \exclude - constexpr const T&& operator*() const&& { - return std::move(this->m_value); - } -#endif - - /// \returns whether or not the optional has a value - /// \group has_value - constexpr bool has_value() const noexcept { - return this->m_has_value; - } - - /// \group has_value - constexpr explicit operator bool() const noexcept { - return this->m_has_value; - } - - /// \returns the contained value if there is one, otherwise throws - /// [bad_optional_access] - /// \group value - /// \synopsis constexpr T &value(); - SOL_TL_OPTIONAL_11_CONSTEXPR T& value() & { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - /// \group value - /// \synopsis constexpr const T &value() const; - SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const& { - if (has_value()) - return this->m_value; - throw bad_optional_access(); - } - /// \exclude - SOL_TL_OPTIONAL_11_CONSTEXPR T&& value() && { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \exclude - SOL_TL_OPTIONAL_11_CONSTEXPR const T&& value() const&& { - if (has_value()) - return std::move(this->m_value); - throw bad_optional_access(); - } -#endif - - /// \returns the stored value if there is one, otherwise returns `u` - /// \group value_or - template - constexpr T value_or(U&& u) const& { - static_assert(std::is_copy_constructible::value && std::is_convertible::value, "T must be copy constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// \group value_or - template - SOL_TL_OPTIONAL_11_CONSTEXPR T value_or(U&& u) && { - static_assert(std::is_move_constructible::value && std::is_convertible::value, "T must be move constructible and convertible from U"); - return has_value() ? **this : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept { - if (has_value()) { - this->m_value.~T(); - this->m_has_value = false; - } - } - }; // namespace sol - - /// \group relop - /// \brief Compares two optional objects - /// \details If both optionals contain a value, they are compared with `T`s - /// relational operators. Otherwise `lhs` and `rhs` are equal only if they are - /// both empty, and `lhs` is less than `rhs` only if `rhs` is empty and `lhs` - /// is not. - template - inline constexpr bool operator==(const optional& lhs, const optional& rhs) { - return lhs.has_value() == rhs.has_value() && (!lhs.has_value() || *lhs == *rhs); - } - /// \group relop - template - inline constexpr bool operator!=(const optional& lhs, const optional& rhs) { - return lhs.has_value() != rhs.has_value() || (lhs.has_value() && *lhs != *rhs); - } - /// \group relop - template - inline constexpr bool operator<(const optional& lhs, const optional& rhs) { - return rhs.has_value() && (!lhs.has_value() || *lhs < *rhs); - } - /// \group relop - template - inline constexpr bool operator>(const optional& lhs, const optional& rhs) { - return lhs.has_value() && (!rhs.has_value() || *lhs > *rhs); - } - /// \group relop - template - inline constexpr bool operator<=(const optional& lhs, const optional& rhs) { - return !lhs.has_value() || (rhs.has_value() && *lhs <= *rhs); - } - /// \group relop - template - inline constexpr bool operator>=(const optional& lhs, const optional& rhs) { - return !rhs.has_value() || (lhs.has_value() && *lhs >= *rhs); - } - - /// \group relop_nullopt - /// \brief Compares an optional to a `nullopt` - /// \details Equivalent to comparing the optional to an empty optional - template - inline constexpr bool operator==(const optional& lhs, nullopt_t) noexcept { - return !lhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator==(nullopt_t, const optional& rhs) noexcept { - return !rhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator!=(const optional& lhs, nullopt_t) noexcept { - return lhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator!=(nullopt_t, const optional& rhs) noexcept { - return rhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator<(const optional&, nullopt_t) noexcept { - return false; - } - /// \group relop_nullopt - template - inline constexpr bool operator<(nullopt_t, const optional& rhs) noexcept { - return rhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator<=(const optional& lhs, nullopt_t) noexcept { - return !lhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator<=(nullopt_t, const optional&) noexcept { - return true; - } - /// \group relop_nullopt - template - inline constexpr bool operator>(const optional& lhs, nullopt_t) noexcept { - return lhs.has_value(); - } - /// \group relop_nullopt - template - inline constexpr bool operator>(nullopt_t, const optional&) noexcept { - return false; - } - /// \group relop_nullopt - template - inline constexpr bool operator>=(const optional&, nullopt_t) noexcept { - return true; - } - /// \group relop_nullopt - template - inline constexpr bool operator>=(nullopt_t, const optional& rhs) noexcept { - return !rhs.has_value(); - } - - /// \group relop_t - /// \brief Compares the optional with a value. - /// \details If the optional has a value, it is compared with the other value - /// using `T`s relational operators. Otherwise, the optional is considered - /// less than the value. - template - inline constexpr bool operator==(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs == rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator==(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs == *rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator!=(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs != rhs : true; - } - /// \group relop_t - template - inline constexpr bool operator!=(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs != *rhs : true; - } - /// \group relop_t - template - inline constexpr bool operator<(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs < rhs : true; - } - /// \group relop_t - template - inline constexpr bool operator<(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs < *rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator<=(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs <= rhs : true; - } - /// \group relop_t - template - inline constexpr bool operator<=(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs <= *rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator>(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs > rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator>(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs > *rhs : true; - } - /// \group relop_t - template - inline constexpr bool operator>=(const optional& lhs, const U& rhs) { - return lhs.has_value() ? *lhs >= rhs : false; - } - /// \group relop_t - template - inline constexpr bool operator>=(const U& lhs, const optional& rhs) { - return rhs.has_value() ? lhs >= *rhs : true; - } - - /// \synopsis template \nvoid swap(optional &lhs, optional &rhs); - template ::value>* = nullptr, detail::enable_if_t::value>* = nullptr> - void swap(optional& lhs, optional& rhs) noexcept(noexcept(lhs.swap(rhs))) { - return lhs.swap(rhs); - } - - namespace detail { - struct i_am_secret {}; - } // namespace detail - - template ::value, detail::decay_t, T>> - inline constexpr optional make_optional(U&& v) { - return optional(std::forward(v)); - } - - template - inline constexpr optional make_optional(Args&&... args) { - return optional(in_place, std::forward(args)...); - } - template - inline constexpr optional make_optional(std::initializer_list il, Args&&... args) { - return optional(in_place, il, std::forward(args)...); - } - -#if __cplusplus >= 201703L - template - optional(T)->optional; -#endif - - /// \exclude - namespace detail { -#ifdef SOL_TL_OPTIONAL_CXX14 - template (), *std::declval())), - detail::enable_if_t::value>* = nullptr> - constexpr auto optional_map_impl(Opt&& opt, F&& f) { - return opt.has_value() ? detail::invoke(std::forward(f), *std::forward(opt)) : optional(nullopt); - } - - template (), *std::declval())), - detail::enable_if_t::value>* = nullptr> - auto optional_map_impl(Opt&& opt, F&& f) { - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return make_optional(monostate{}); - } - - return optional(nullopt); - } -#else - template (), *std::declval())), - detail::enable_if_t::value>* = nullptr> - - constexpr auto optional_map_impl(Opt&& opt, F&& f) -> optional { - return opt.has_value() ? detail::invoke(std::forward(f), *std::forward(opt)) : optional(nullopt); - } - - template (), *std::declval())), - detail::enable_if_t::value>* = nullptr> - - auto optional_map_impl(Opt&& opt, F&& f) -> optional { - if (opt.has_value()) { - detail::invoke(std::forward(f), *std::forward(opt)); - return monostate{}; - } - - return nullopt; - } -#endif - } // namespace detail - - /// Specialization for when `T` is a reference. `optional` acts similarly - /// to a `T*`, but provides more operations and shows intent more clearly. - /// - /// *Examples*: - /// - /// ``` - /// int i = 42; - /// sol::optional o = i; - /// *o == 42; //true - /// i = 12; - /// *o = 12; //true - /// &*o == &i; //true - /// ``` - /// - /// Assignment has rebind semantics rather than assign-through semantics: - /// - /// ``` - /// int j = 8; - /// o = j; - /// - /// &*o == &j; //true - /// ``` - template - class optional { - public: -// The different versions for C++14 and 11 are needed because deduced return -// types are not SFINAE-safe. This provides better support for things like -// generic lambdas. C.f. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html -#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto and_then(F&& f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr auto and_then(F&& f) const& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr auto and_then(F&& f) const&& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } -#endif -#else - /// \group and_then - /// Carries out some operation which returns an optional on the stored - /// object if there is one. \requires `std::invoke(std::forward(f), - /// value())` returns a `std::optional` for some `U`. \returns Let `U` be - /// the result of `std::invoke(std::forward(f), value())`. Returns a - /// `std::optional`. The return value is empty if `*this` is empty, - /// otherwise the return value of `std::invoke(std::forward(f), value())` - /// is returned. - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) & { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR detail::invoke_result_t and_then(F&& f) && { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &; - template - constexpr detail::invoke_result_t and_then(F&& f) const& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group and_then - /// \synopsis template \nconstexpr auto and_then(F &&f) const &&; - template - constexpr detail::invoke_result_t and_then(F&& f) const&& { - using result = detail::invoke_result_t; - static_assert(detail::is_optional::value, "F must return an optional"); - - return has_value() ? detail::invoke(std::forward(f), **this) : result(nullopt); - } -#endif -#endif - -#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55) - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template constexpr auto map(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) & { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR auto map(F&& f) && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&; - template - constexpr auto map(F&& f) const& { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template constexpr auto map(F &&f) const&&; - template - constexpr auto map(F&& f) const&& { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#else - /// \brief Carries out some operation on the stored object if there is one. - /// \returns Let `U` be the result of `std::invoke(std::forward(f), - /// value())`. Returns a `std::optional`. The return value is empty if - /// `*this` is empty, otherwise an `optional` is constructed from the - /// return value of `std::invoke(std::forward(f), value())` and is - /// returned. - /// - /// \group map - /// \synopsis template auto map(F &&f) &; - template - SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval(), std::declval())) map(F&& f) & { - return detail::optional_map_impl(*this, std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) &&; - template - SOL_TL_OPTIONAL_11_CONSTEXPR decltype(detail::optional_map_impl(std::declval(), std::declval())) map(F&& f) && { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } - - /// \group map - /// \synopsis template auto map(F &&f) const&; - template - constexpr decltype(detail::optional_map_impl(std::declval(), std::declval())) map(F&& f) const& { - return detail::optional_map_impl(*this, std::forward(f)); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map - /// \synopsis template auto map(F &&f) const&&; - template - constexpr decltype(detail::optional_map_impl(std::declval(), std::declval())) map(F&& f) const&& { - return detail::optional_map_impl(std::move(*this), std::forward(f)); - } -#endif -#endif - - /// \brief Calls `f` if the optional is empty - /// \requires `std::invoke_result_t` must be void or convertible to - /// `optional`. \effects If `*this` has a value, returns `*this`. - /// Otherwise, if `f` returns `void`, calls `std::forward(f)` and returns - /// `std::nullopt`. Otherwise, returns `std::forward(f)()`. - /// - /// \group or_else - /// \synopsis template optional or_else (F &&f) &; - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) & { - return has_value() ? *this : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) &&; - template * = nullptr> - optional or_else(F&& f) && { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) && { - return has_value() ? std::move(*this) : std::forward(f)(); - } - - /// \group or_else - /// \synopsis template optional or_else (F &&f) const &; - template * = nullptr> - optional or_else(F&& f) const& { - if (has_value()) - return *this; - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional SOL_TL_OPTIONAL_11_CONSTEXPR or_else(F&& f) const& { - return has_value() ? *this : std::forward(f)(); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \exclude - template * = nullptr> - optional or_else(F&& f) const&& { - if (has_value()) - return std::move(*this); - - std::forward(f)(); - return nullopt; - } - - /// \exclude - template * = nullptr> - optional or_else(F&& f) const&& { - return has_value() ? std::move(*this) : std::forward(f)(); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise returns - /// `u`. - /// - /// \details If there is a value stored, then `f` is called with `**this` - /// and the value is returned. Otherwise `u` is returned. - /// - /// \group map_or - template - U map_or(F&& f, U&& u) & { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u); - } - - /// \group map_or - template - U map_or(F&& f, U&& u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u); - } - - /// \group map_or - template - U map_or(F&& f, U&& u) const& { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map_or - template - U map_or(F&& f, U&& u) const&& { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u); - } -#endif - - /// \brief Maps the stored value with `f` if there is one, otherwise calls - /// `u` and returns the result. - /// - /// \details If there is a value stored, then `f` is - /// called with `**this` and the value is returned. Otherwise - /// `std::forward(u)()` is returned. - /// - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) &; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) & { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// &&; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) && { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u)(); - } - - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const& { - return has_value() ? detail::invoke(std::forward(f), **this) : std::forward(u)(); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group map_or_else - /// \synopsis template \nauto map_or_else(F &&f, U &&u) - /// const &&; - template - detail::invoke_result_t map_or_else(F&& f, U&& u) const&& { - return has_value() ? detail::invoke(std::forward(f), std::move(**this)) : std::forward(u)(); - } -#endif - - /// \returns `u` if `*this` has a value, otherwise an empty optional. - template - constexpr optional::type> conjunction(U&& u) const { - using result = optional>; - return has_value() ? result{ u } : result{ nullopt }; - } - - /// \returns `rhs` if `*this` is empty, otherwise the current value. - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) & { - return has_value() ? *this : rhs; - } - - /// \group disjunction - constexpr optional disjunction(const optional& rhs) const& { - return has_value() ? *this : rhs; - } - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(const optional& rhs) && { - return has_value() ? std::move(*this) : rhs; - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(const optional& rhs) const&& { - return has_value() ? std::move(*this) : rhs; - } -#endif - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) & { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - constexpr optional disjunction(optional&& rhs) const& { - return has_value() ? *this : std::move(rhs); - } - - /// \group disjunction - SOL_TL_OPTIONAL_11_CONSTEXPR optional disjunction(optional&& rhs) && { - return has_value() ? std::move(*this) : std::move(rhs); - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group disjunction - constexpr optional disjunction(optional&& rhs) const&& { - return has_value() ? std::move(*this) : std::move(rhs); - } -#endif - - /// Takes the value out of the optional, leaving it empty - /// \group take - optional take() & { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() const& { - optional ret = *this; - reset(); - return ret; - } - - /// \group take - optional take() && { - optional ret = std::move(*this); - reset(); - return ret; - } - -#ifndef SOL_TL_OPTIONAL_NO_CONSTRR - /// \group take - optional take() const&& { - optional ret = std::move(*this); - reset(); - return ret; - } -#endif - - using value_type = T&; - - /// Constructs an optional that does not contain a value. - /// \group ctor_empty - constexpr optional() noexcept : m_value(nullptr) { - } - - /// \group ctor_empty - constexpr optional(nullopt_t) noexcept : m_value(nullptr) { - } - - /// Copy constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - SOL_TL_OPTIONAL_11_CONSTEXPR optional(const optional& rhs) noexcept = default; - - /// Move constructor - /// - /// If `rhs` contains a value, the stored value is direct-initialized with - /// it. Otherwise, the constructed optional is empty. - SOL_TL_OPTIONAL_11_CONSTEXPR optional(optional&& rhs) = default; - - /// Constructs the stored value with `u`. - /// \synopsis template constexpr optional(U &&u); - template >::value>* = nullptr> - constexpr optional(U&& u) : m_value(std::addressof(u)) { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - } - - /// \exclude - template - constexpr explicit optional(const optional& rhs) : optional(*rhs) { - } - - /// No-op - ~optional() = default; - - /// Assignment to empty. - /// - /// Destroys the current value if there is one. - optional& operator=(nullopt_t) noexcept { - m_value = nullptr; - return *this; - } - - /// Copy assignment. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - optional& operator=(const optional& rhs) = default; - - /// Rebinds this optional to `u`. - /// - /// \requires `U` must be an lvalue reference. - /// \synopsis optional &operator=(U &&u); - template >::value>* = nullptr> - optional& operator=(U&& u) { - static_assert(std::is_lvalue_reference::value, "U must be an lvalue"); - m_value = std::addressof(u); - return *this; - } - - /// Converting copy assignment operator. - /// - /// Rebinds this optional to the referee of `rhs` if there is one. Otherwise - /// resets the stored value in `*this`. - template - optional& operator=(const optional& rhs) { - m_value = std::addressof(rhs.value()); - return *this; - } - - /// Constructs the value in-place, destroying the current one if there is - /// one. - /// - /// \group emplace - template - T& emplace(Args&&... args) noexcept { - static_assert(std::is_constructible::value, "T must be constructible with Args"); - - *this = nullopt; - this->construct(std::forward(args)...); - } - - /// Swaps this optional with the other. - /// - /// If neither optionals have a value, nothing happens. - /// If both have a value, the values are swapped. - /// If one has a value, it is moved to the other and the movee is left - /// valueless. - void swap(optional& rhs) noexcept { - std::swap(m_value, rhs.m_value); - } - - /// \returns a pointer to the stored value - /// \requires a value is stored - /// \group pointer - /// \synopsis constexpr const T *operator->() const; - constexpr const T* operator->() const { - return m_value; - } - - /// \group pointer - /// \synopsis constexpr T *operator->(); - SOL_TL_OPTIONAL_11_CONSTEXPR T* operator->() { - return m_value; - } - - /// \returns the stored value - /// \requires a value is stored - /// \group deref - /// \synopsis constexpr T &operator*(); - SOL_TL_OPTIONAL_11_CONSTEXPR T& operator*() { - return *m_value; - } - - /// \group deref - /// \synopsis constexpr const T &operator*() const; - constexpr const T& operator*() const { - return *m_value; - } - - /// \returns whether or not the optional has a value - /// \group has_value - constexpr bool has_value() const noexcept { - return m_value != nullptr; - } - - /// \group has_value - constexpr explicit operator bool() const noexcept { - return m_value != nullptr; - } - - /// \returns the contained value if there is one, otherwise throws - /// [bad_optional_access] - /// \group value - /// synopsis constexpr T &value(); - SOL_TL_OPTIONAL_11_CONSTEXPR T& value() { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - /// \group value - /// \synopsis constexpr const T &value() const; - SOL_TL_OPTIONAL_11_CONSTEXPR const T& value() const { - if (has_value()) - return *m_value; - throw bad_optional_access(); - } - - /// \returns the stored value if there is one, otherwise returns `u` - /// \group value_or - template - constexpr T& value_or(U&& u) const { - static_assert(std::is_convertible::value, "T must be convertible from U"); - return has_value() ? const_cast(**this) : static_cast(std::forward(u)); - } - - /// Destroys the stored value if one exists, making the optional empty - void reset() noexcept { - m_value = nullptr; - } - - private: - T* m_value; - }; - -} // namespace sol - -namespace std { - // TODO SFINAE - template - struct hash< ::sol::optional > { - ::std::size_t operator()(const ::sol::optional& o) const { - if (!o.has_value()) - return 0; - - return ::std::hash< ::sol::detail::remove_const_t>()(*o); - } - }; -} // namespace std - -#endif // SOL_TL_OPTIONAL_HPP -- cgit v1.2.3