diff --git a/sol/forward.hpp b/sol/forward.hpp index dc5758fa..bcc472bc 100644 --- a/sol/forward.hpp +++ b/sol/forward.hpp @@ -26,6 +26,8 @@ #include "feature_test.hpp" +#include + namespace sol { template @@ -158,6 +160,24 @@ namespace sol { struct usertype_traits; template struct unique_usertype_traits; + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template + struct derive : std::false_type { + typedef types<> type; + }; + + template + struct base : std::false_type { + typedef types<> type; + }; } // namespace sol #endif // SOL_FORWARD_HPP diff --git a/sol/inheritance.hpp b/sol/inheritance.hpp index abd9dcff..9c0cad75 100644 --- a/sol/inheritance.hpp +++ b/sol/inheritance.hpp @@ -38,16 +38,6 @@ namespace sol { namespace detail { - template - struct derive : std::false_type { - typedef types<> type; - }; - - template - struct base : std::false_type { - typedef types<> type; - }; - inline decltype(auto) base_class_check_key() { static const auto& key = "class_check"; return key; @@ -68,8 +58,10 @@ namespace sol { return key; } - template + template struct inheritance { + typedef typename base::type bases_t; + static bool type_check_bases(types<>, const std::string&) { return false; } @@ -80,7 +72,7 @@ namespace sol { } static bool type_check(const std::string& ti) { - return ti == usertype_traits::qualified_name() || type_check_bases(types(), ti); + return ti == usertype_traits::qualified_name() || type_check_bases(bases_t(), ti); } static void* type_cast_bases(types<>, T*, const std::string&) { @@ -95,16 +87,16 @@ namespace sol { static void* type_cast(void* voiddata, const std::string& ti) { T* data = static_cast(voiddata); - return static_cast(ti != usertype_traits::qualified_name() ? type_cast_bases(types(), data, ti) : data); + return static_cast(ti != usertype_traits::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data); } template - static bool type_unique_cast_bases(void*, void*, const string_view&) { - return false; + static bool type_unique_cast_bases(types<>, void*, void*, const string_view&) { + return 0; } template - static bool type_unique_cast_bases(void* source_data, void* target_data, const string_view& ti) { + 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; string_view base_ti = usertype_traits::qualified_name(); @@ -115,21 +107,26 @@ namespace sol { // perform proper derived -> base conversion *target = *source; } - return true; + return 2; } - return type_unique_cast_bases(source_data, target_data, ti); + return type_unique_cast_bases(types(), source_data, target_data, ti); } template - static bool type_unique_cast(void* source_data, void* target_data, const string_view& ti, const string_view& rebind_ti) { + 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 typename uu_traits::template rebind_base rebind_t; string_view this_rebind_ti = usertype_traits::qualified_name(); if (rebind_ti != this_rebind_ti) { - // this is not even of the same container type - return false; + // this is not even of the same unique type + return 0; } - return type_unique_cast_bases(source_data, target_data, ti); + string_view this_ti = usertype_traits::qualified_name(); + if (ti == this_ti) { + // + return 1; + } + return type_unique_cast_bases(bases_t(), source_data, target_data, ti); } }; @@ -139,4 +136,7 @@ namespace sol { } // namespace detail } // namespace sol +#define SOL_BASE_CLASSES(T, ...) template <> struct ::sol::base : ::std::true_type { typedef ::sol::types<__VA_ARGS__> type; }; +//#define SOL_DERIVED_CLASSES(T, ...) template <> struct ::sol::derive : ::std::true_type { typedef ::sol::types<__VA_ARGS__> type; }; + #endif // SOL_INHERITANCE_HPP diff --git a/sol/stack_check_qualified.hpp b/sol/stack_check_qualified.hpp index 3f346267..9b9eebbe 100644 --- a/sol/stack_check_qualified.hpp +++ b/sol/stack_check_qualified.hpp @@ -29,11 +29,14 @@ namespace sol { namespace stack { -#if 0 template - struct qualified_checker::value && !std::is_reference::value>> { + struct qualified_checker::value + && !std::is_reference::value + >> { typedef unique_usertype_traits> u_traits; typedef typename u_traits::type T; + typedef typename u_traits::template rebind_base rebind_t; template static bool check(std::false_type, lua_State* L, int index, Handler&& handler, record& tracking) { @@ -50,23 +53,19 @@ namespace stack { handler(L, index, type::userdata, indextype, "value is not a userdata"); return false; } - if (lua_getmetatable(L, index) == 0) { - return true; - } - int metatableindex = lua_gettop(L); - void* basecastdata = lua_touserdata(L, index); - void* memory = detail::align_usertype_unique_destructor(basecastdata); + void* memory = lua_touserdata(L, index); + memory = detail::align_usertype_unique_destructor(memory); detail::unique_destructor& pdx = *static_cast(memory); if (&detail::usertype_unique_alloc_destroy == pdx) { return true; } - if (detail::has_derived::value) { - memory = detail::align_usertype_unique_cast(memory); - detail::inheritance_unique_cast_function ic = reinterpret_cast(memory); + if (derive::value) { + memory = detail::align_usertype_unique_tag(memory); + detail::unique_tag& ic = *reinterpret_cast(memory); string_view ti = usertype_traits::qualified_name(); - string_view rebind_ti = usertype_traits::qualified_name(); - if (ic(nullptr, basecastdata, ti, rebind_ti)) { - lua_pop(L, 1); + string_view rebind_ti = usertype_traits::qualified_name(); + if (ic(nullptr, nullptr, ti, rebind_ti) != 0) { + return true; } } handler(L, index, type::userdata, indextype, "value is a userdata but is not the correct unique usertype"); @@ -75,12 +74,10 @@ namespace stack { template static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { - return check(meta::neg>(), L, index, std::forward(handler), tracking); + return check(meta::neg>(), L, index, std::forward(handler), tracking); } }; -#endif // Not implemented right now... - template struct qualified_checker>::value && !std::is_reference::value>> { template diff --git a/sol/stack_check_unqualified.hpp b/sol/stack_check_unqualified.hpp index 33b5b634..30921540 100644 --- a/sol/stack_check_unqualified.hpp +++ b/sol/stack_check_unqualified.hpp @@ -473,7 +473,7 @@ namespace stack { if (stack_detail::check_metatable>(L, metatableindex)) return true; bool success = false; - if (detail::derive::value) { + if (derive::value) { auto pn = stack::pop_n(L, 1); lua_pushstring(L, &detail::base_class_check_key()[0]); lua_rawget(L, metatableindex); diff --git a/sol/stack_core.hpp b/sol/stack_core.hpp index f3a2b789..70853d7e 100644 --- a/sol/stack_core.hpp +++ b/sol/stack_core.hpp @@ -52,11 +52,7 @@ namespace sol { struct as_table_tag {}; using unique_destructor = void (*)(void*); -#if 0 using unique_tag = detail::inheritance_unique_cast_function; -#else - using unique_tag = const char*; -#endif inline void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space, std::size_t& required_space) { // this handels arbitrary alignments... @@ -108,7 +104,7 @@ namespace sol { return align(std::alignment_of::value, sizeof(void*), ptr, space); } - template + template inline void* align_usertype_unique_destructor(void* ptr) { typedef std::integral_constant(static_cast(ptr) + sizeof(void*)); } if (!use_align::value) { @@ -129,7 +127,7 @@ namespace sol { return align(std::alignment_of::value, sizeof(unique_destructor), ptr, space); } - template + template inline void* align_usertype_unique_tag(void* ptr) { typedef std::integral_constant(static_cast(ptr) + sizeof(unique_destructor)); } if (!use_align::value) { @@ -149,7 +149,8 @@ namespace sol { std::size_t space = (std::numeric_limits::max)(); return align(std::alignment_of::value, sizeof(unique_tag), ptr, space); } - template + + template inline void* align_usertype_unique(void* ptr) { typedef std::integral_constant(static_cast(ptr) + sizeof(unique_tag)); } if (!use_align::value) { diff --git a/sol/stack_get_qualified.hpp b/sol/stack_get_qualified.hpp index bcdd8110..d5e765fd 100644 --- a/sol/stack_get_qualified.hpp +++ b/sol/stack_get_qualified.hpp @@ -29,24 +29,57 @@ namespace sol { namespace stack { -#if 0 // need static reflection / DERIVED_CLASS macros... template struct qualified_getter::value && is_unique_usertype>::value + !std::is_reference::value + && is_unique_usertype>::value >> { - typedef typename unique_usertype_traits>::type P; - typedef typename unique_usertype_traits>::actual_type Real; + typedef unique_usertype_traits> u_traits; + typedef typename u_traits::type T; + typedef typename u_traits::actual_type Real; + typedef typename u_traits::template rebind_base rebind_t; - static Real& get(lua_State* L, int index, record& tracking) { + static Real get(lua_State* L, int index, record& tracking) { tracking.use(1); void* memory = lua_touserdata(L, index); - void* del = detail::align_usertype_unique_destructor(memory); - memory = detail::align_usertype_unique(memory); - Real* mem = static_cast(memory); - return *mem; + memory = detail::align_usertype_unique_destructor(memory); + detail::unique_destructor& pdx = *static_cast(memory); + if (&detail::usertype_unique_alloc_destroy == pdx) { + memory = detail::align_usertype_unique_tag(memory); + memory = detail::align_usertype_unique(memory); + Real* mem = static_cast(memory); + return *mem; + } + Real r(nullptr); + if (!derive::value) { + // TODO: abort / terminate, maybe only in debug modes? + return r; + } + 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); + switch (cast_operation) { + case 1: { + // it's a perfect match, + // alias memory directly + Real* mem = static_cast(memory); + return *mem; + } + case 2: + // it's a base match, return the + // aliased creation + return std::move(r); + default: + // uh oh.. + break; + } + // TODO: abort / terminate, maybe only in debug modes? + return r; } }; -#endif // need static reflection template struct qualified_getter::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { + if (derive::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { void* basecastdata = lua_touserdata(L, -1); detail::inheritance_cast_function ic = reinterpret_cast(basecastdata); // use the casting function to properly adjust the pointer for the desired T diff --git a/sol/stack_push.hpp b/sol/stack_push.hpp index d452d435..0f3541f9 100644 --- a/sol/stack_push.hpp +++ b/sol/stack_push.hpp @@ -167,11 +167,7 @@ namespace stack { detail::unique_tag* id = nullptr; Real* mem = detail::usertype_unique_allocate(L, pref, fx, id); *fx = detail::usertype_unique_alloc_destroy; -#if 0 - *id = &detail::inheritance

::type_unique_cast_bases; -#else - *id = &usertype_traits::qualified_name()[0]; -#endif + *id = &detail::inheritance

::type_unique_cast; detail::default_construct::construct(mem, std::forward(args)...); *pref = unique_usertype_traits::get(*mem); if (luaL_newmetatable(L, &usertype_traits>>::metatable()[0]) == 1) { diff --git a/sol/tuple.hpp b/sol/tuple.hpp index 25067956..ff67729a 100644 --- a/sol/tuple.hpp +++ b/sol/tuple.hpp @@ -32,13 +32,6 @@ namespace sol { using swallow = std::initializer_list; } // namespace detail - template - struct types { - typedef std::make_index_sequence indices; - static constexpr std::size_t size() { - return sizeof...(Args); - } - }; namespace meta { namespace detail { template