mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
add ability to have aliasing arguments
This commit is contained in:
parent
860827cb0a
commit
96143d8d79
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include "feature_test.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace sol {
|
||||
|
||||
template <bool b>
|
||||
|
@ -158,6 +160,24 @@ namespace sol {
|
|||
struct usertype_traits;
|
||||
template <typename T>
|
||||
struct unique_usertype_traits;
|
||||
|
||||
template <typename... Args>
|
||||
struct types {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> indices;
|
||||
static constexpr std::size_t size() {
|
||||
return sizeof...(Args);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct derive : std::false_type {
|
||||
typedef types<> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct base : std::false_type {
|
||||
typedef types<> type;
|
||||
};
|
||||
} // namespace sol
|
||||
|
||||
#endif // SOL_FORWARD_HPP
|
||||
|
|
|
@ -38,16 +38,6 @@ namespace sol {
|
|||
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
struct derive : std::false_type {
|
||||
typedef types<> type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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 <typename T, typename... Bases>
|
||||
template <typename T>
|
||||
struct inheritance {
|
||||
typedef typename base<T>::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<T>::qualified_name() || type_check_bases(types<Bases...>(), ti);
|
||||
return ti == usertype_traits<T>::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<T*>(voiddata);
|
||||
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(types<Bases...>(), data, ti) : data);
|
||||
return static_cast<void*>(ti != usertype_traits<T>::qualified_name() ? type_cast_bases(bases_t(), data, ti) : data);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
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 <typename U, typename Base, typename... Args>
|
||||
static bool type_unique_cast_bases(void* source_data, void* target_data, const string_view& ti) {
|
||||
static int type_unique_cast_bases(types<Base, Args...>, void* source_data, void* target_data, const string_view& ti) {
|
||||
typedef unique_usertype_traits<U> uu_traits;
|
||||
typedef typename uu_traits::template rebind_base<Base> base_ptr;
|
||||
string_view base_ti = usertype_traits<Base>::qualified_name();
|
||||
|
@ -115,21 +107,26 @@ namespace sol {
|
|||
// perform proper derived -> base conversion
|
||||
*target = *source;
|
||||
}
|
||||
return true;
|
||||
return 2;
|
||||
}
|
||||
return type_unique_cast_bases<U, Args...>(source_data, target_data, ti);
|
||||
return type_unique_cast_bases<U>(types<Args...>(), source_data, target_data, ti);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
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<U> uu_traits;
|
||||
typedef typename uu_traits::template rebind_base<T> rebind_t;
|
||||
typedef typename uu_traits::template rebind_base<void> rebind_t;
|
||||
string_view this_rebind_ti = usertype_traits<rebind_t>::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<U, Bases...>(source_data, target_data, ti);
|
||||
string_view this_ti = usertype_traits<T>::qualified_name();
|
||||
if (ti == this_ti) {
|
||||
//
|
||||
return 1;
|
||||
}
|
||||
return type_unique_cast_bases<U>(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<T> : ::std::true_type { typedef ::sol::types<__VA_ARGS__> type; };
|
||||
//#define SOL_DERIVED_CLASSES(T, ...) template <> struct ::sol::derive<T> : ::std::true_type { typedef ::sol::types<__VA_ARGS__> type; };
|
||||
|
||||
#endif // SOL_INHERITANCE_HPP
|
||||
|
|
|
@ -29,11 +29,14 @@
|
|||
namespace sol {
|
||||
namespace stack {
|
||||
|
||||
#if 0
|
||||
template <typename X>
|
||||
struct qualified_checker<X, type::userdata, std::enable_if_t<is_unique_usertype<X>::value && !std::is_reference<X>::value>> {
|
||||
struct qualified_checker<X, type::userdata, std::enable_if_t<
|
||||
is_unique_usertype<X>::value
|
||||
&& !std::is_reference<X>::value
|
||||
>> {
|
||||
typedef unique_usertype_traits<meta::unqualified_t<X>> u_traits;
|
||||
typedef typename u_traits::type T;
|
||||
typedef typename u_traits::template rebind_base<void> rebind_t;
|
||||
|
||||
template <typename Handler>
|
||||
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<detail::unique_destructor*>(memory);
|
||||
if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
|
||||
return true;
|
||||
}
|
||||
if (detail::has_derived<T>::value) {
|
||||
memory = detail::align_usertype_unique_cast<true>(memory);
|
||||
detail::inheritance_unique_cast_function ic = reinterpret_cast<detail::inheritance_unique_cast_function>(memory);
|
||||
if (derive<T>::value) {
|
||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
||||
string_view ti = usertype_traits<T>::qualified_name();
|
||||
string_view rebind_ti = usertype_traits<base_id>::qualified_name();
|
||||
if (ic(nullptr, basecastdata, ti, rebind_ti)) {
|
||||
lua_pop(L, 1);
|
||||
string_view rebind_ti = usertype_traits<rebind_t>::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 <typename Handler>
|
||||
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||
return check(meta::neg<std::is_void<typename u_traits::base_id>>(), L, index, std::forward<Handler>(handler), tracking);
|
||||
return check(meta::neg<std::is_void<rebind_t>>(), L, index, std::forward<Handler>(handler), tracking);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // Not implemented right now...
|
||||
|
||||
template <typename X>
|
||||
struct qualified_checker<X, type::userdata, std::enable_if_t<is_container<meta::unqualified_t<X>>::value && !std::is_reference<X>::value>> {
|
||||
template <typename Handler>
|
||||
|
|
|
@ -473,7 +473,7 @@ namespace stack {
|
|||
if (stack_detail::check_metatable<as_container_t<U>>(L, metatableindex))
|
||||
return true;
|
||||
bool success = false;
|
||||
if (detail::derive<T>::value) {
|
||||
if (derive<T>::value) {
|
||||
auto pn = stack::pop_n(L, 1);
|
||||
lua_pushstring(L, &detail::base_class_check_key()[0]);
|
||||
lua_rawget(L, metatableindex);
|
||||
|
|
|
@ -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<void*>::value, sizeof(void*), ptr, space);
|
||||
}
|
||||
|
||||
template <bool pre_aligned = false>
|
||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||
inline void* align_usertype_unique_destructor(void* ptr) {
|
||||
typedef std::integral_constant<bool,
|
||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||
|
@ -120,6 +116,8 @@ namespace sol {
|
|||
use_align;
|
||||
if (!pre_aligned) {
|
||||
ptr = align_usertype_pointer(ptr);
|
||||
}
|
||||
if (!pre_shifted) {
|
||||
ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(void*));
|
||||
}
|
||||
if (!use_align::value) {
|
||||
|
@ -129,7 +127,7 @@ namespace sol {
|
|||
return align(std::alignment_of<unique_destructor>::value, sizeof(unique_destructor), ptr, space);
|
||||
}
|
||||
|
||||
template <bool pre_aligned = false>
|
||||
template <bool pre_aligned = false, bool pre_shifted = false>
|
||||
inline void* align_usertype_unique_tag(void* ptr) {
|
||||
typedef std::integral_constant<bool,
|
||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||
|
@ -141,6 +139,8 @@ namespace sol {
|
|||
use_align;
|
||||
if (!pre_aligned) {
|
||||
ptr = align_usertype_unique_destructor(ptr);
|
||||
}
|
||||
if (!pre_shifted) {
|
||||
ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_destructor));
|
||||
}
|
||||
if (!use_align::value) {
|
||||
|
@ -149,7 +149,8 @@ namespace sol {
|
|||
std::size_t space = (std::numeric_limits<std::size_t>::max)();
|
||||
return align(std::alignment_of<unique_tag>::value, sizeof(unique_tag), ptr, space);
|
||||
}
|
||||
template <typename T, bool pre_aligned = false>
|
||||
|
||||
template <typename T, bool pre_aligned = false, bool pre_shifted = false>
|
||||
inline void* align_usertype_unique(void* ptr) {
|
||||
typedef std::integral_constant<bool,
|
||||
#if defined(SOL_NO_MEMORY_ALIGNMENT) && SOL_NO_MEMORY_ALIGNMENT
|
||||
|
@ -161,6 +162,8 @@ namespace sol {
|
|||
use_align;
|
||||
if (!pre_aligned) {
|
||||
ptr = align_usertype_unique_tag(ptr);
|
||||
}
|
||||
if (!pre_shifted) {
|
||||
ptr = static_cast<void*>(static_cast<char*>(ptr) + sizeof(unique_tag));
|
||||
}
|
||||
if (!use_align::value) {
|
||||
|
|
|
@ -29,24 +29,57 @@
|
|||
namespace sol {
|
||||
namespace stack {
|
||||
|
||||
#if 0 // need static reflection / DERIVED_CLASS macros...
|
||||
template <typename X>
|
||||
struct qualified_getter<X, std::enable_if_t<
|
||||
!std::is_reference<X>::value && is_unique_usertype<meta::unqualified_t<X>>::value
|
||||
!std::is_reference<X>::value
|
||||
&& is_unique_usertype<meta::unqualified_t<X>>::value
|
||||
>> {
|
||||
typedef typename unique_usertype_traits<meta::unqualified_t<X>>::type P;
|
||||
typedef typename unique_usertype_traits<meta::unqualified_t<X>>::actual_type Real;
|
||||
typedef unique_usertype_traits<meta::unqualified_t<X>> u_traits;
|
||||
typedef typename u_traits::type T;
|
||||
typedef typename u_traits::actual_type Real;
|
||||
typedef typename u_traits::template rebind_base<void> 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<Real>(memory);
|
||||
Real* mem = static_cast<Real*>(memory);
|
||||
return *mem;
|
||||
memory = detail::align_usertype_unique_destructor(memory);
|
||||
detail::unique_destructor& pdx = *static_cast<detail::unique_destructor*>(memory);
|
||||
if (&detail::usertype_unique_alloc_destroy<T, X> == pdx) {
|
||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||
Real* mem = static_cast<Real*>(memory);
|
||||
return *mem;
|
||||
}
|
||||
Real r(nullptr);
|
||||
if (!derive<T>::value) {
|
||||
// TODO: abort / terminate, maybe only in debug modes?
|
||||
return r;
|
||||
}
|
||||
memory = detail::align_usertype_unique_tag<true, false>(memory);
|
||||
detail::unique_tag& ic = *reinterpret_cast<detail::unique_tag*>(memory);
|
||||
memory = detail::align_usertype_unique<Real, true, false>(memory);
|
||||
string_view ti = usertype_traits<T>::qualified_name();
|
||||
string_view rebind_ti = usertype_traits<rebind_t>::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<Real*>(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 <typename T>
|
||||
struct qualified_getter<T, std::enable_if_t<
|
||||
|
@ -68,3 +101,4 @@ namespace stack {
|
|||
} // namespace sol::stack
|
||||
|
||||
#endif // SOL_STACK_QUALIFIED_GET_HPP
|
||||
|
||||
|
|
|
@ -759,7 +759,7 @@ namespace stack {
|
|||
}
|
||||
|
||||
static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) {
|
||||
if (detail::derive<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) {
|
||||
if (derive<T>::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<detail::inheritance_cast_function>(basecastdata);
|
||||
// use the casting function to properly adjust the pointer for the desired T
|
||||
|
|
|
@ -167,11 +167,7 @@ namespace stack {
|
|||
detail::unique_tag* id = nullptr;
|
||||
Real* mem = detail::usertype_unique_allocate<P, Real>(L, pref, fx, id);
|
||||
*fx = detail::usertype_unique_alloc_destroy<P, Real>;
|
||||
#if 0
|
||||
*id = &detail::inheritance<P>::type_unique_cast_bases<Real>;
|
||||
#else
|
||||
*id = &usertype_traits<Real>::qualified_name()[0];
|
||||
#endif
|
||||
*id = &detail::inheritance<P>::type_unique_cast<Real>;
|
||||
detail::default_construct::construct(mem, std::forward<Args>(args)...);
|
||||
*pref = unique_usertype_traits<T>::get(*mem);
|
||||
if (luaL_newmetatable(L, &usertype_traits<detail::unique_usertype<std::remove_cv_t<P>>>::metatable()[0]) == 1) {
|
||||
|
|
|
@ -32,13 +32,6 @@ namespace sol {
|
|||
using swallow = std::initializer_list<int>;
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Args>
|
||||
struct types {
|
||||
typedef std::make_index_sequence<sizeof...(Args)> indices;
|
||||
static constexpr std::size_t size() {
|
||||
return sizeof...(Args);
|
||||
}
|
||||
};
|
||||
namespace meta {
|
||||
namespace detail {
|
||||
template <typename... Args>
|
||||
|
|
Loading…
Reference in New Issue
Block a user