Let's do iiiit.

This commit is contained in:
ThePhD 2016-07-28 13:33:08 -04:00
parent 08b5204dee
commit de359acb3e
11 changed files with 75 additions and 161 deletions

View File

@ -74,18 +74,18 @@ Explanations for a few categories are below (rest are self-explanatory).
* optional: Support for getting an element, or potentially not (and not forcing the default construction of what amounts to a bogus/dead object). Usually comes with ``std(::experimental)::optional``. It's a fairly new class, so a hand-rolled class internal to the library with similar semantics is also acceptable * optional: Support for getting an element, or potentially not (and not forcing the default construction of what amounts to a bogus/dead object). Usually comes with ``std(::experimental)::optional``. It's a fairly new class, so a hand-rolled class internal to the library with similar semantics is also acceptable
* tables: Some sort of abstraction for dealing with tables. Ideal support is ``mytable["some_key"] = value``, and everything that the syntax implies. * tables: Some sort of abstraction for dealing with tables. Ideal support is ``mytable["some_key"] = value``, and everything that the syntax implies.
* table chaining: In conjunction with tables, having the ability to do nest deeply into tables ``mytable["key1"]["key2"]["key3"]``. Note that this becomes a tripping point for some libraries: crashing if ``"key1"`` doesn't exist while trying to access ``"key2"`` (Sol avoids this specifically when you use ``sol::optional``), and sometimes it's also a heavy performance bottleneck as expressions are not lazy-evaluated by a library. * table chaining: In conjunction with tables, having the ability to query deeply into tables ``mytable["key1"]["key2"]["key3"]``. Note that this becomes a tripping point for some libraries: crashing if ``"key1"`` doesn't exist while trying to access ``"key2"`` (Sol avoids this specifically when you use ``sol::optional``), and sometimes it's also a heavy performance bottleneck as expressions are not lazy-evaluated by a library.
* arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table without dropping to the plain API. * arbitrary keys: Letting C++ code use userdata, other tables, integers, etc. as keys for into a table.
* user-defined types (udts): C++ types given form and function in lua code. * user-defined types (udts): C++ types given form and function in Lua code.
* udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua. * udts - member functions: C++ member functions on a type, usually callable with ``my_object:foo(1)`` or similar in Lua.
* udts - variables: C++ member variables, manipulated by ``my_object.var = 24`` and friends * udts - variables: C++ member variables, manipulated by ``my_object.var = 24`` and friends
* function binding: Support for binding all types of functions. Lambdas, member functions, free functions, in different contexts, etc... * function binding: Support for binding all types of functions. Lambdas, member functions, free functions, in different contexts, etc...
* protected function: Use of ``lua_pcall`` to call a function, which offers error-handling and trampolining * protected function: Use of ``lua_pcall`` to call a function, which offers error-handling and trampolining (as well as the ability to opt-in / opt-out of this behavior)
* multi-return: returning multiple values from and to lua * multi-return: returning multiple values from and to Lua (generally through ``std::tuple<...>`` or in some other way)
* variadic/variant argument: being able to accept "anything" from lua, and even return "anything" to lua * variadic/variant argument: being able to accept "anything" from Lua, and even return "anything" to Lua (``object`` abstraction, variadic arguments, etc...)
* inheritance: allowing some degree of subtyping or inheritance on classes / userdata from lua * inheritance: allowing some degree of subtyping or inheritance on classes / userdata from Lua - this generally means that you can retrieve a base pointer from Lua even if you hand the library a derived pointer
* overloading: the ability to call overloaded functions, matched based on arity or type (``foo( 1 )`` from lua calls a different function then ``foo( "bark" )``). * overloading: the ability to call overloaded functions, matched based on arity or type (``foo( 1 )`` from lua calls a different function then ``foo( "bark" )``).
* lua thread: basic wrapping of the lua thread API; ties in with coroutine. * Lua thread: basic wrapping of the lua thread API; ties in with coroutine.
* coroutines: allowing a function to be called multiple times, resuming the execution of a Lua coroutine each time * coroutines: allowing a function to be called multiple times, resuming the execution of a Lua coroutine each time
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
@ -112,7 +112,7 @@ Explanations for a few categories are below (rest are self-explanatory).
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ | | function binding | ~ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ~ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| protected function | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ~ | | protected call | ~ | ✗ | ~ | ~ | ~ | ✔ | ~ | ✔ | ~ | ~ | ~ | ~ | ~ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ✗ | | multi-return | ~ | ✗ | ✔ | ✔ | ✔ | ✔ | ~ | ✔ | ✔ | ~ | ✔ | ~ | ✗ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
@ -122,7 +122,7 @@ Explanations for a few categories are below (rest are self-explanatory).
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | | overloading | ~ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| lua thread | ~ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | | Lua thread | ~ | ✗ | ~ | ✗ | ✗ | ✔ | ✔ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+
| coroutines | ~ | ✗ | ~ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ | | coroutines | ~ | ✗ | ~ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ | ✗ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+ +---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+----------+-----------+-----------------+--------+

View File

@ -367,7 +367,7 @@ namespace sol {
int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) { int operator()(types<Fx>, index_value<I>, types<R...> r, types<Args...> a, lua_State* L, int, int start, F& f) {
const auto& metakey = usertype_traits<T>::metatable; const auto& metakey = usertype_traits<T>::metatable;
T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T))); T** pointerpointer = reinterpret_cast<T**>(lua_newuserdata(L, sizeof(T*) + sizeof(T)));
stack_reference userdataref(L, -1); reference userdataref(L, -1);
T*& referencepointer = *pointerpointer; T*& referencepointer = *pointerpointer;
T* obj = reinterpret_cast<T*>(pointerpointer + 1); T* obj = reinterpret_cast<T*>(pointerpointer + 1);
referencepointer = obj; referencepointer = obj;

View File

@ -23,9 +23,7 @@
#define SOL_INHERITANCE_HPP #define SOL_INHERITANCE_HPP
#include "types.hpp" #include "types.hpp"
#if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
#include <atomic> #include <atomic>
#endif // No Runtime Type Information and No Exceptions
namespace sol { namespace sol {
template <typename... Args> template <typename... Args>
@ -46,7 +44,6 @@ namespace sol {
template <typename T> template <typename T>
bool has_derived<T>::value = false; bool has_derived<T>::value = false;
#if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
inline std::size_t unique_id() { inline std::size_t unique_id() {
static std::atomic<std::size_t> x(0); static std::atomic<std::size_t> x(0);
return ++x; return ++x;
@ -59,7 +56,6 @@ namespace sol {
template <typename T> template <typename T>
const std::size_t id_for<T>::value = unique_id(); const std::size_t id_for<T>::value = unique_id();
#endif // No Runtime Type Information / No Exceptions
inline decltype(auto) base_class_check_key() { inline decltype(auto) base_class_check_key() {
static const auto& key = u8"♡o。.(✿ฺ。 ✿ฺ)"; static const auto& key = u8"♡o。.(✿ฺ。 ✿ฺ)";
@ -71,112 +67,39 @@ namespace sol {
return key; return key;
} }
#ifndef SOL_NO_EXCEPTIONS
template <typename T>
void throw_as(void* p) {
throw static_cast<T*>(p);
}
using throw_cast = decltype(&throw_as<void>);
template <typename T>
inline T* catch_cast(void* p, throw_cast f) {
try {
f(static_cast<void*>(p));
}
catch (T* ptr) {
return ptr;
}
catch (...) {
return static_cast<T*>(p);
}
return static_cast<T*>(p);
}
template <typename T>
inline bool catch_check(throw_cast f) {
try {
f(nullptr);
}
catch (T*) {
return true;
}
catch (...) {
return false;
}
return false;
}
#elif !defined(SOL_NO_RTTI)
template <typename T, typename... Bases> template <typename T, typename... Bases>
struct inheritance { struct inheritance {
static bool type_check(types<>, const std::type_info&) { static bool type_check_bases(types<>, std::size_t) {
return false; return false;
} }
template <typename Base, typename... Args> template <typename Base, typename... Args>
static bool type_check(types<Base, Args...>, const std::type_info& ti) { static bool type_check_bases(types<Base, Args...>, std::size_t ti) {
return ti != typeid(Base) || type_check(types<Bases...>(), ti); return ti != id_for<Base>::value || type_check_bases(types<Args...>(), ti);
}
static bool type_check(const std::type_info& ti) {
return ti != typeid(T) || type_check(types<Bases...>(), ti);
}
static void* type_cast(types<>, T*, const std::type_info& ti) {
return nullptr;
}
template <typename Base, typename... Args>
static void* type_cast(types<Base, Args...>, T* data, const std::type_info& ti) {
// Make sure to convert to T first, and then dynamic cast to the proper type
return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
}
static void* type_cast(void* voiddata, const std::type_info& ti) {
T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
}
};
using inheritance_check_function = decltype(&inheritance<void>::type_check);
using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
#else
template <typename T, typename... Bases>
struct inheritance {
static bool type_check(types<>, std::size_t) {
return false;
}
template <typename Base, typename... Args>
static bool type_check(types<Base, Args...>, std::size_t ti) {
return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
} }
static bool type_check(std::size_t ti) { static bool type_check(std::size_t ti) {
return ti != id_for<T>::value || type_check(types<Bases...>(), ti); return ti != id_for<T>::value || type_check_bases(types<Bases...>(), ti);
} }
static void* type_cast(types<>, T*, std::size_t) { static void* type_cast_bases(types<>, T*, std::size_t) {
return nullptr; return nullptr;
} }
template <typename Base, typename... Args> template <typename Base, typename... Args>
static void* type_cast(types<Base, Args...>, T* data, std::size_t ti) { static void* type_cast_bases(types<Base, Args...>, T* data, std::size_t ti) {
// Make sure to convert to T first, and then dynamic cast to the proper type // Make sure to convert to T first, and then dynamic cast to the proper type
return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data)); return ti != id_for<Base>::value ? type_cast_bases(types<Args...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
} }
static void* type_cast(void* voiddata, std::size_t ti) { static void* type_cast(void* voiddata, std::size_t ti) {
T* data = static_cast<T*>(voiddata); T* data = static_cast<T*>(voiddata);
return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data); return static_cast<void*>(ti != id_for<T>::value ? type_cast_bases(types<Bases...>(), data, ti) : data);
} }
}; };
using inheritance_check_function = decltype(&inheritance<void>::type_check); using inheritance_check_function = decltype(&inheritance<void>::type_check);
using inheritance_cast_function = decltype(&inheritance<void>::type_cast); using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
#endif // No Exceptions and/or No Runtime Type Information
} // detail } // detail
} // sol } // sol

View File

@ -93,7 +93,9 @@ namespace sol {
object make_reference(lua_State* L, Args&&... args) { object make_reference(lua_State* L, Args&&... args) {
int backpedal = stack::push<T>(L, std::forward<Args>(args)...); int backpedal = stack::push<T>(L, std::forward<Args>(args)...);
object r = stack::get<sol::object>(L, -backpedal); object r = stack::get<sol::object>(L, -backpedal);
if (should_pop) {
lua_pop(L, backpedal); lua_pop(L, backpedal);
}
return r; return r;
} }

View File

@ -27,6 +27,17 @@
namespace sol { namespace sol {
namespace stack { namespace stack {
template <bool top_level>
struct push_popper_n {
lua_State* L;
int t;
push_popper_n(lua_State* L, int x) : L(L), t(x) { }
~push_popper_n() { lua_pop(L, t); }
};
template <>
struct push_popper_n<true> {
push_popper_n(lua_State*, int) { }
};
template <bool top_level, typename T> template <bool top_level, typename T>
struct push_popper { struct push_popper {
T t; T t;
@ -42,6 +53,10 @@ namespace sol {
push_popper<top_level, T> push_pop(T&& x) { push_popper<top_level, T> push_pop(T&& x) {
return push_popper<top_level, T>(std::forward<T>(x)); return push_popper<top_level, T>(std::forward<T>(x));
} }
template <bool top_level = false>
push_popper_n<top_level> pop_n(lua_State* L, int x) {
return push_popper_n<top_level>(L, x);
}
} // stack } // stack
namespace detail { namespace detail {
@ -135,9 +150,8 @@ namespace sol {
} }
type get_type() const noexcept { type get_type() const noexcept {
push(); auto pp = stack::push_pop(*this);
int result = lua_type(L, -1); int result = lua_type(L, -1);
lua_pop(L, 1);
return static_cast<type>(result); return static_cast<type>(result);
} }

View File

@ -148,12 +148,14 @@ namespace sol {
template<bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs> template<bool check_args = stack_detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { inline int call_into_lua(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); call<check_args>(tr, ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
lua_settop(L, 0);
return 0; return 0;
} }
template<bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>> template<bool check_args = stack_detail::default_check_arguments, typename Ret0, typename... Ret, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<meta::neg<std::is_void<Ret0>>::value>>
inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { inline int call_into_lua(types<Ret0, Ret...>, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) {
decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...); decltype(auto) r = call<check_args>(types<meta::return_type_t<Ret0, Ret...>>(), ta, L, start, std::forward<Fx>(fx), std::forward<FxArgs>(fxargs)...);
lua_settop(L, 0);
return push_reference(L, std::forward<decltype(r)>(r)); return push_reference(L, std::forward<decltype(r)>(r));
} }
@ -167,11 +169,10 @@ namespace sol {
inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) { inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index = -2) {
luaL_getmetatable(L, key.c_str()); luaL_getmetatable(L, key.c_str());
auto pn = pop_n(L, 1);
if (lua_compare(L, -1, index, LUA_OPEQ) == 1) { if (lua_compare(L, -1, index, LUA_OPEQ) == 1) {
lua_pop(L, 1);
return call_syntax::colon; return call_syntax::colon;
} }
lua_pop(L, 1);
return call_syntax::dot; return call_syntax::dot;
} }
@ -190,8 +191,8 @@ namespace sol {
inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) {
#ifdef SOL_LUAJIT #ifdef SOL_LUAJIT
lua_pushlightuserdata(L, (void*)handler); lua_pushlightuserdata(L, (void*)handler);
auto pn = pop_n(L, 1);
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON);
lua_pop(L, 1);
#else #else
(void)L; (void)L;
(void)handler; (void)handler;

View File

@ -209,14 +209,14 @@ namespace sol {
static const auto& callkey = name_of(meta_function::call); static const auto& callkey = name_of(meta_function::call);
lua_getmetatable(L, index); lua_getmetatable(L, index);
if (lua_isnoneornil(L, -1)) { if (lua_isnoneornil(L, -1)) {
handler(L, index, t, type::function);
lua_pop(L, 1); lua_pop(L, 1);
handler(L, index, t, type::function);
return false; return false;
} }
lua_getfield(L, -1, &callkey[0]); lua_getfield(L, -1, &callkey[0]);
if (lua_isnoneornil(L, -1)) { if (lua_isnoneornil(L, -1)) {
handler(L, index, t, type::function);
lua_pop(L, 2); lua_pop(L, 2);
handler(L, index, t, type::function);
return false; return false;
} }
// has call, is definitely a function // has call, is definitely a function
@ -274,30 +274,15 @@ namespace sol {
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L)) if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
return true; return true;
bool success = false; bool success = false;
#ifndef SOL_NO_EXCEPTIONS {
lua_getfield(L, -1, &detail::base_class_check_key()[0]); auto pn = stack::pop_n(L, 2);
if (type_of(L, -1) != type::nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
success = detail::catch_check<T>(basecast);
}
#elif !defined(SOL_NO_RTTI)
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
if (type_of(L, -1) != type::nil) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
success = ic(typeid(T));
}
#else
// Topkek
lua_getfield(L, -1, &detail::base_class_check_key()[0]); lua_getfield(L, -1, &detail::base_class_check_key()[0]);
if (type_of(L, -1) != type::nil) { if (type_of(L, -1) != type::nil) {
void* basecastdata = lua_touserdata(L, -1); void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
success = ic(detail::id_for<T>::value); success = ic(detail::id_for<T>::value);
} }
#endif // No Runtime Type Information || Exceptions }
lua_pop(L, 2);
if (!success) { if (!success) {
handler(L, index, type::userdata, indextype); handler(L, index, type::userdata, indextype);
return false; return false;

View File

@ -289,24 +289,6 @@ namespace sol {
} }
static T* get_no_nil_from(lua_State* L, void* udata, int index = -1) { static T* get_no_nil_from(lua_State* L, void* udata, int index = -1) {
#ifndef SOL_NO_EXCEPTIONS
if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_check_key()[0]) != 0) {
void* basecastdata = lua_touserdata(L, -1);
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
// use the casting function to properly adjust the pointer for the desired T
udata = detail::catch_cast<T>(udata, basecast);
lua_pop(L, 1);
}
#elif !defined(SOL_NO_RTTI)
if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) {
void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
// use the casting function to properly adjust the pointer for the desired T
udata = ic(udata, typeid(T));
lua_pop(L, 1);
}
#else
// Lol, you motherfucker
if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { if (detail::has_derived<T>::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) {
void* basecastdata = lua_touserdata(L, -1); void* basecastdata = lua_touserdata(L, -1);
detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata;
@ -314,7 +296,6 @@ namespace sol {
udata = ic(udata, detail::id_for<T>::value); udata = ic(udata, detail::id_for<T>::value);
lua_pop(L, 1); lua_pop(L, 1);
} }
#endif // No Runtime Type Information || Exceptions
T* obj = static_cast<T*>(udata); T* obj = static_cast<T*>(udata);
return obj; return obj;
} }

View File

@ -54,8 +54,8 @@ namespace sol {
sol::object key(base_t::lua_state(), -2); sol::object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1); sol::object value(base_t::lua_state(), -1);
std::pair<sol::object&, sol::object&> keyvalue(key, value); std::pair<sol::object&, sol::object&> keyvalue(key, value);
auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(keyvalue); fx(keyvalue);
lua_pop(base_t::lua_state(), 1);
} }
} }
@ -66,8 +66,8 @@ namespace sol {
while (lua_next(base_t::lua_state(), -2)) { while (lua_next(base_t::lua_state(), -2)) {
sol::object key(base_t::lua_state(), -2); sol::object key(base_t::lua_state(), -2);
sol::object value(base_t::lua_state(), -1); sol::object value(base_t::lua_state(), -1);
auto pn = stack::pop_n(base_t::lua_state(), 1);
fx(key, value); fx(key, value);
lua_pop(base_t::lua_state(), 1);
} }
} }
@ -231,8 +231,8 @@ namespace sol {
template <typename... Keys> template <typename... Keys>
basic_table_core& traverse_set(Keys&&... keys) { basic_table_core& traverse_set(Keys&&... keys) {
auto pp = stack::push_pop<is_global<Keys...>::value>(*this); auto pp = stack::push_pop<is_global<Keys...>::value>(*this);
auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys)-2));
traverse_set_deep<top_level>(std::forward<Keys>(keys)...); traverse_set_deep<top_level>(std::forward<Keys>(keys)...);
lua_pop(base_t::lua_state(), static_cast<int>(sizeof...(Keys)-2));
return *this; return *this;
} }

View File

@ -188,20 +188,11 @@ namespace sol {
return; return;
} }
(void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... }; (void)detail::swallow{ 0, ((detail::has_derived<Bases>::value = true), 0)... };
#ifndef SOL_NO_EXCEPTIONS
static_assert(sizeof(void*) <= sizeof(detail::throw_cast), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
baseclasscheck = baseclasscast = (void*)&detail::throw_as<T>;
#elif !defined(SOL_NO_RTTI)
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
baseclasscheck = (void*)&detail::inheritance<T, Args...>::type_check; baseclasscheck = (void*)&detail::inheritance<T, Bases...>::type_check;
baseclasscast = (void*)&detail::inheritance<T, Args...>::type_cast; baseclasscast = (void*)&detail::inheritance<T, Bases...>::type_cast;
#else
static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report.");
baseclasscheck = (void*)&detail::inheritance<T, Args...>::type_check;
baseclasscast = (void*)&detail::inheritance<T, Args...>::type_cast;
#endif // No Runtime Type Information vs. Throw-Style Inheritance
} }
template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>> template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>>

View File

@ -627,6 +627,23 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak
REQUIRE(expectednumkilled == factory_test::num_killed); REQUIRE(expectednumkilled == factory_test::num_killed);
} }
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
struct A { int x = 201; };
struct B {
int foo(const A* a) { return a->x; };
};
sol::state lua;
lua.new_usertype<B>("B",
"foo", &B::foo
);
lua.set("a", A());
lua.set("b", B());
lua.script("x = b:foo(a)");
int x = lua["x"];
REQUIRE(x == 201);
}
TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") { TEST_CASE("usertype/overloading", "Check if overloading works properly for usertypes") {
struct woof { struct woof {
int var; int var;