diff --git a/docs/source/api/unique_usertype_traits.rst b/docs/source/api/unique_usertype_traits.rst index 723f0991..00794fd4 100644 --- a/docs/source/api/unique_usertype_traits.rst +++ b/docs/source/api/unique_usertype_traits.rst @@ -29,14 +29,14 @@ This is a customization point for users who need to *work with special kinds of typedef boost::shared_ptr actual_type; static const bool value = true; - static bool is_null(const actual_type& value) { - return value == nullptr; + static bool is_null(const actual_type& ptr) { + return ptr == nullptr; } - static type* get (const actual_type& p) { - return p.get(); + static type* get (const actual_type& ptr) { + return ptr.get(); } - } + }; } This will allow the library to properly handle ``boost::shared_ptr``, with ref-counting and all. The ``type`` is the type that lua and sol will interact with, and will allow you to pull out a non-owning reference / pointer to the data when you just ask for a plain ``T*`` or ``T&`` or ``T`` using the getter functions and properties of Sol. The ``actual_type`` is just the "real type" that controls the semantics (shared, unique, ``CComPtr``, ``ComPtr``, OpenGL handles, DirectX objects, the list goes on). diff --git a/include/sol/call.hpp b/include/sol/call.hpp index 495bc1e6..3322cfc6 100644 --- a/include/sol/call.hpp +++ b/include/sol/call.hpp @@ -30,6 +30,7 @@ #include "trampoline.hpp" #include "filters.hpp" #include "stack.hpp" +#include "unique_usertype_traits.hpp" namespace sol { namespace u_detail { diff --git a/include/sol/inheritance.hpp b/include/sol/inheritance.hpp index bcc656ee..68799e5a 100644 --- a/include/sol/inheritance.hpp +++ b/include/sol/inheritance.hpp @@ -26,6 +26,7 @@ #include "types.hpp" #include "usertype_traits.hpp" +#include "unique_usertype_traits.hpp" namespace sol { template @@ -108,8 +109,8 @@ namespace sol { template static int type_unique_cast_bases(types, void* source_data, void* target_data, const string_view& ti) { - typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base base_ptr; + using uu_traits = unique_usertype_traits; + using base_ptr = typename uu_traits::template rebind_base; string_view base_ti = usertype_traits::qualified_name(); if (base_ti == ti) { if (target_data != nullptr) { @@ -126,38 +127,60 @@ namespace sol { template static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base rebind_t; - typedef meta::conditional_t::value, types<>, bases_t> cond_bases_t; - string_view this_rebind_ti = usertype_traits::qualified_name(); - if (rebind_ti != this_rebind_ti) { - // this is not even of the same unique type - return 0; + if constexpr (is_base_rebindable_v) { + typedef typename uu_traits::template rebind_base rebind_t; + typedef meta::conditional_t::value, types<>, bases_t> cond_bases_t; + string_view this_rebind_ti = usertype_traits::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } - string_view this_ti = usertype_traits::qualified_name(); - if (ti == this_ti) { - // direct match, return 1 - return 1; + else { + (void)rebind_ti; + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(types<>(), source_data, target_data, ti); } - return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } template static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { using uc_bases_t = types; typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base rebind_t; - typedef meta::conditional_t::value, types<>, uc_bases_t> cond_bases_t; - string_view this_rebind_ti = usertype_traits::qualified_name(); - if (rebind_ti != this_rebind_ti) { - // this is not even of the same unique type - return 0; + if constexpr (is_base_rebindable_v) { + using rebind_t = typename uu_traits::template rebind_base; + using cond_bases_t = meta::conditional_t::value, types<>, uc_bases_t>; + string_view this_rebind_ti = usertype_traits::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } - string_view this_ti = usertype_traits::qualified_name(); - if (ti == this_ti) { - // direct match, return 1 - return 1; + else { + (void)rebind_ti; + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(types<>(), source_data, target_data, ti); } - return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } }; diff --git a/include/sol/stack_check_get_unqualified.hpp b/include/sol/stack_check_get_unqualified.hpp index 52f507b7..65f0ebf7 100644 --- a/include/sol/stack_check_get_unqualified.hpp +++ b/include/sol/stack_check_get_unqualified.hpp @@ -33,6 +33,9 @@ #include #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES #include +#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT +#include +#endif // variant #endif // C++17 @@ -64,20 +67,20 @@ namespace stack { tracking.use(1); return static_cast(lua_tointeger(L, index)); } - #endif +#endif int isnum = 0; const lua_Number value = lua_tonumberx(L, index, &isnum); if (isnum != 0) { - #if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) +#if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) const auto integer_value = llround(value); if (static_cast(integer_value) == value) { tracking.use(1); return static_cast(integer_value); } - #else +#else tracking.use(1); return static_cast(value); - #endif +#endif } const type t = type_of(L, index); tracking.use(static_cast(t != type::none)); @@ -146,8 +149,8 @@ namespace stack { }; #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT - template - struct unqualified_check_getter> { + template + struct unqualified_check_getter, C> { typedef std::variant V; typedef std::variant_size V_size; typedef std::integral_constant V_is_empty; diff --git a/include/sol/stack_get_unqualified.hpp b/include/sol/stack_get_unqualified.hpp index 182c3037..9495bcd5 100644 --- a/include/sol/stack_get_unqualified.hpp +++ b/include/sol/stack_get_unqualified.hpp @@ -174,12 +174,10 @@ namespace sol { namespace stack { return stack_detail::unchecked_unqualified_get>(L, index, tracking); } } - else if constexpr (!std::is_reference_v< - X> && is_unique_usertype_v && !std::is_void_v::template rebind_base>) { + else if constexpr (!std::is_reference_v && is_unique_usertype_v && !is_base_rebindable_non_void_v>) { using u_traits = unique_usertype_traits; using T = typename u_traits::type; using Real = typename u_traits::actual_type; - using rebind_t = typename u_traits::template rebind_base; tracking.use(1); void* memory = lua_touserdata(L, index); memory = detail::align_usertype_unique_destructor(memory); @@ -193,15 +191,23 @@ namespace sol { namespace stack { Real r(nullptr); if constexpr (!derive::value) { // TODO: abort / terminate, maybe only in debug modes? - return static_cast(r); + return static_cast(std::move(r)); } else { memory = detail::align_usertype_unique_tag(memory); detail::unique_tag& ic = *reinterpret_cast(memory); memory = detail::align_usertype_unique(memory); string_view ti = usertype_traits::qualified_name(); - string_view rebind_ti = usertype_traits::qualified_name(); - int cast_operation = ic(memory, &r, ti, rebind_ti); + int cast_operation; + if constexpr (is_base_rebindable_v) { + using rebind_t = typename u_traits::template rebind_base; + string_view rebind_ti = usertype_traits::qualified_name(); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + else { + string_view rebind_ti(""); + cast_operation = ic(memory, &r, ti, rebind_ti); + } switch (cast_operation) { case 1: { // it's a perfect match, @@ -974,8 +980,6 @@ namespace sol { namespace stack { }; #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES - - #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT template struct unqualified_getter> { @@ -1012,6 +1016,7 @@ namespace sol { namespace stack { }; #endif // SOL_STD_VARIANT #endif // SOL_CXX17_FEATURES + }} // namespace sol::stack #endif // SOL_STACK_UNQUALIFIED_GET_HPP diff --git a/include/sol/stack_push.hpp b/include/sol/stack_push.hpp index 0e1e38cb..f9dd93a1 100644 --- a/include/sol/stack_push.hpp +++ b/include/sol/stack_push.hpp @@ -196,7 +196,6 @@ namespace sol { using u_traits = unique_usertype_traits; using P = typename u_traits::type; using Real = typename u_traits::actual_type; - using rebind_t = typename u_traits::template rebind_base; template static int push(lua_State* L, Arg&& arg, Args&&... args) { diff --git a/include/sol/types.hpp b/include/sol/types.hpp index c896e2d0..6469f655 100644 --- a/include/sol/types.hpp +++ b/include/sol/types.hpp @@ -148,65 +148,6 @@ namespace sol { typedef std::remove_pointer_t lua_CFunction_ref; - template - struct unique_usertype_traits { - typedef T type; - typedef T actual_type; - template - using rebind_base = void; - - static const bool value = false; - - template - static bool is_null(U&&) { - return false; - } - - template - static auto get(U&& value) { - return std::addressof(detail::deref(value)); - } - }; - - template - struct unique_usertype_traits> { - typedef T type; - typedef std::shared_ptr actual_type; - // rebind is non-void - // if and only if unique usertype - // is cast-capable - template - using rebind_base = std::shared_ptr; - - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template - struct unique_usertype_traits> { - typedef T type; - typedef std::unique_ptr actual_type; - template - using rebind_base = void; - - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - template struct non_null {}; @@ -1176,12 +1117,6 @@ namespace sol { struct accumulate_list> : accumulate {}; } // namespace detail - template - struct is_unique_usertype : std::integral_constant::value> {}; - - template - inline constexpr bool is_unique_usertype_v = is_unique_usertype::value; - template struct lua_type_of : detail::lua_type_of { typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; diff --git a/include/sol/unique_usertype_traits.hpp b/include/sol/unique_usertype_traits.hpp new file mode 100644 index 00000000..c1433a61 --- /dev/null +++ b/include/sol/unique_usertype_traits.hpp @@ -0,0 +1,124 @@ +// sol3 + +// 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. + +#ifndef SOL_UNIQUE_USERTYPE_TRAITS_HPP +#define SOL_UNIQUE_USERTYPE_TRAITS_HPP + +#include "base_traits.hpp" + +#include + +namespace sol { + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + template + using rebind_base = void; + + static const bool value = false; + + template + static bool is_null(U&&) { + return false; + } + + template + static auto get(U&& value) { + return std::addressof(detail::deref(value)); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::shared_ptr actual_type; + // rebind is non-void + // if and only if unique usertype + // is cast-capable + template + using rebind_base = std::shared_ptr; + + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct unique_usertype_traits> { + using type = T; + using actual_type = std::unique_ptr; + + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct is_unique_usertype : std::integral_constant::value> {}; + + template + inline constexpr bool is_unique_usertype_v = is_unique_usertype::value; + + namespace detail { + template + using is_base_rebindable_test = decltype(T::rebind_base); + } + + template + using is_base_rebindable = meta::is_detected; + + template + inline constexpr bool is_base_rebindable_v = is_base_rebindable::value; + + namespace detail { + template + struct is_base_rebindable_non_void_sfinae : std::false_type {}; + + template + struct is_base_rebindable_non_void_sfinae>> + : std::integral_constant>> {}; + } // namespace detail + + template + using is_base_rebindable_non_void = meta::is_detected; + + template + inline constexpr bool is_base_rebindable_non_void_v = is_base_rebindable_non_void::value; + +} // namespace sol + +#endif // SOL_UNIQUE_USERTYPE_TRAITS_HPP diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index 470c27b1..f14e726c 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-04-08 03:11:15.372045 UTC -// This header was generated with sol v3.0.1-beta2 (revision 7cce3e4) +// Generated 2019-04-13 08:04:51.418277 UTC +// This header was generated with sol v3.0.1-beta2 (revision d17f967) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index 9ade98af..cce238e0 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -20,8 +20,8 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2019-04-08 03:11:10.821035 UTC -// This header was generated with sol v3.0.1-beta2 (revision 7cce3e4) +// Generated 2019-04-13 08:04:48.327520 UTC +// This header was generated with sol v3.0.1-beta2 (revision d17f967) // https://github.com/ThePhD/sol2 #ifndef SOL_SINGLE_INCLUDE_HPP @@ -6276,65 +6276,6 @@ namespace sol { typedef std::remove_pointer_t lua_CFunction_ref; - template - struct unique_usertype_traits { - typedef T type; - typedef T actual_type; - template - using rebind_base = void; - - static const bool value = false; - - template - static bool is_null(U&&) { - return false; - } - - template - static auto get(U&& value) { - return std::addressof(detail::deref(value)); - } - }; - - template - struct unique_usertype_traits> { - typedef T type; - typedef std::shared_ptr actual_type; - // rebind is non-void - // if and only if unique usertype - // is cast-capable - template - using rebind_base = std::shared_ptr; - - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - - template - struct unique_usertype_traits> { - typedef T type; - typedef std::unique_ptr actual_type; - template - using rebind_base = void; - - static const bool value = true; - - static bool is_null(const actual_type& p) { - return p == nullptr; - } - - static type* get(const actual_type& p) { - return p.get(); - } - }; - template struct non_null {}; @@ -7304,12 +7245,6 @@ namespace sol { struct accumulate_list> : accumulate {}; } // namespace detail - template - struct is_unique_usertype : std::integral_constant::value> {}; - - template - inline constexpr bool is_unique_usertype_v = is_unique_usertype::value; - template struct lua_type_of : detail::lua_type_of { typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; @@ -7923,6 +7858,103 @@ namespace sol { // end of sol/usertype_traits.hpp +// beginning of sol/unique_usertype_traits.hpp + +namespace sol { + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + template + using rebind_base = void; + + static const bool value = false; + + template + static bool is_null(U&&) { + return false; + } + + template + static auto get(U&& value) { + return std::addressof(detail::deref(value)); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::shared_ptr actual_type; + // rebind is non-void + // if and only if unique usertype + // is cast-capable + template + using rebind_base = std::shared_ptr; + + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct unique_usertype_traits> { + using type = T; + using actual_type = std::unique_ptr; + + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct is_unique_usertype : std::integral_constant::value> {}; + + template + inline constexpr bool is_unique_usertype_v = is_unique_usertype::value; + + namespace detail { + template + using is_base_rebindable_test = decltype(T::rebind_base); + } + + template + using is_base_rebindable = meta::is_detected; + + template + inline constexpr bool is_base_rebindable_v = is_base_rebindable::value; + + namespace detail { + template + struct is_base_rebindable_non_void_sfinae : std::false_type {}; + + template + struct is_base_rebindable_non_void_sfinae>> + : std::integral_constant>> {}; + } // namespace detail + + template + using is_base_rebindable_non_void = meta::is_detected; + + template + inline constexpr bool is_base_rebindable_non_void_v = is_base_rebindable_non_void::value; + +} // namespace sol + +// end of sol/unique_usertype_traits.hpp + namespace sol { template struct base_list {}; @@ -8004,8 +8036,8 @@ namespace sol { template static int type_unique_cast_bases(types, void* source_data, void* target_data, const string_view& ti) { - typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base base_ptr; + using uu_traits = unique_usertype_traits; + using base_ptr = typename uu_traits::template rebind_base; string_view base_ti = usertype_traits::qualified_name(); if (base_ti == ti) { if (target_data != nullptr) { @@ -8022,38 +8054,60 @@ namespace sol { template static int type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base rebind_t; - typedef meta::conditional_t::value, types<>, bases_t> cond_bases_t; - string_view this_rebind_ti = usertype_traits::qualified_name(); - if (rebind_ti != this_rebind_ti) { - // this is not even of the same unique type - return 0; + if constexpr (is_base_rebindable_v) { + typedef typename uu_traits::template rebind_base rebind_t; + typedef meta::conditional_t::value, types<>, bases_t> cond_bases_t; + string_view this_rebind_ti = usertype_traits::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } - string_view this_ti = usertype_traits::qualified_name(); - if (ti == this_ti) { - // direct match, return 1 - return 1; + else { + (void)rebind_ti; + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(types<>(), source_data, target_data, ti); } - return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } template static int type_unique_cast_with(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { using uc_bases_t = types; typedef unique_usertype_traits uu_traits; - typedef typename uu_traits::template rebind_base rebind_t; - typedef meta::conditional_t::value, types<>, uc_bases_t> cond_bases_t; - string_view this_rebind_ti = usertype_traits::qualified_name(); - if (rebind_ti != this_rebind_ti) { - // this is not even of the same unique type - return 0; + if constexpr (is_base_rebindable_v) { + using rebind_t = typename uu_traits::template rebind_base; + using cond_bases_t = meta::conditional_t::value, types<>, uc_bases_t>; + string_view this_rebind_ti = usertype_traits::qualified_name(); + if (rebind_ti != this_rebind_ti) { + // this is not even of the same unique type + return 0; + } + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } - string_view this_ti = usertype_traits::qualified_name(); - if (ti == this_ti) { - // direct match, return 1 - return 1; + else { + (void)rebind_ti; + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // direct match, return 1 + return 1; + } + return type_unique_cast_bases(types<>(), source_data, target_data, ti); } - return type_unique_cast_bases(cond_bases_t(), source_data, target_data, ti); } }; @@ -11548,12 +11602,10 @@ namespace sol { namespace stack { return stack_detail::unchecked_unqualified_get>(L, index, tracking); } } - else if constexpr (!std::is_reference_v< - X> && is_unique_usertype_v && !std::is_void_v::template rebind_base>) { + else if constexpr (!std::is_reference_v && is_unique_usertype_v && !is_base_rebindable_non_void_v>) { using u_traits = unique_usertype_traits; using T = typename u_traits::type; using Real = typename u_traits::actual_type; - using rebind_t = typename u_traits::template rebind_base; tracking.use(1); void* memory = lua_touserdata(L, index); memory = detail::align_usertype_unique_destructor(memory); @@ -11567,15 +11619,23 @@ namespace sol { namespace stack { Real r(nullptr); if constexpr (!derive::value) { // TODO: abort / terminate, maybe only in debug modes? - return static_cast(r); + return static_cast(std::move(r)); } else { memory = detail::align_usertype_unique_tag(memory); detail::unique_tag& ic = *reinterpret_cast(memory); memory = detail::align_usertype_unique(memory); string_view ti = usertype_traits::qualified_name(); - string_view rebind_ti = usertype_traits::qualified_name(); - int cast_operation = ic(memory, &r, ti, rebind_ti); + int cast_operation; + if constexpr (is_base_rebindable_v) { + using rebind_t = typename u_traits::template rebind_base; + string_view rebind_ti = usertype_traits::qualified_name(); + cast_operation = ic(memory, &r, ti, rebind_ti); + } + else { + string_view rebind_ti(""); + cast_operation = ic(memory, &r, ti, rebind_ti); + } switch (cast_operation) { case 1: { // it's a perfect match, @@ -12348,7 +12408,6 @@ namespace sol { namespace stack { }; #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES - #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT template struct unqualified_getter> { @@ -12385,6 +12444,7 @@ namespace sol { namespace stack { }; #endif // SOL_STD_VARIANT #endif // SOL_CXX17_FEATURES + }} // namespace sol::stack // end of sol/stack_get_unqualified.hpp @@ -12410,6 +12470,8 @@ namespace stack { // beginning of sol/stack_check_get_unqualified.hpp #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES +#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT +#endif // variant #endif // C++17 namespace sol { @@ -12439,20 +12501,20 @@ namespace stack { tracking.use(1); return static_cast(lua_tointeger(L, index)); } - #endif +#endif int isnum = 0; const lua_Number value = lua_tonumberx(L, index, &isnum); if (isnum != 0) { - #if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) +#if (defined(SOL_SAFE_NUMERICS) && SOL_SAFE_NUMERICS) && !(defined(SOL_NO_CHECK_NUMBER_PRECISION) && SOL_NO_CHECK_NUMBER_PRECISION) const auto integer_value = llround(value); if (static_cast(integer_value) == value) { tracking.use(1); return static_cast(integer_value); } - #else +#else tracking.use(1); return static_cast(value); - #endif +#endif } const type t = type_of(L, index); tracking.use(static_cast(t != type::none)); @@ -12521,8 +12583,8 @@ namespace stack { }; #if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT - template - struct unqualified_check_getter> { + template + struct unqualified_check_getter, C> { typedef std::variant V; typedef std::variant_size V_size; typedef std::integral_constant V_is_empty; @@ -12785,7 +12847,6 @@ namespace sol { using u_traits = unique_usertype_traits; using P = typename u_traits::type; using Real = typename u_traits::actual_type; - using rebind_t = typename u_traits::template rebind_base; template static int push(lua_State* L, Arg&& arg, Args&&... args) { diff --git a/tests/compile_tests/source/unique_usertype_traits.cpp b/tests/compile_tests/source/unique_usertype_traits.cpp new file mode 100644 index 00000000..8c6cf6d9 --- /dev/null +++ b/tests/compile_tests/source/unique_usertype_traits.cpp @@ -0,0 +1,26 @@ +// sol3 + +// 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. + +#include "sol_defines.hpp" + +#include