Add more tests and fix smaller errors with overloading and such.

This commit is contained in:
ThePhD 2016-07-09 01:12:33 -04:00
parent 115dfe39eb
commit 14ced4af69
11 changed files with 568 additions and 400 deletions

View File

@ -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 2016-07-08 00:10:28.267637 UTC
// This header was generated with sol v2.9.0 (revision f7108d5)
// Generated 2016-07-09 04:51:51.604138 UTC
// This header was generated with sol v2.9.0 (revision 115dfe3)
// https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP
@ -325,6 +325,7 @@ namespace sol {
typedef std::tuple<Arg> args_tuple;
typedef R return_type;
typedef types<Arg> args_list;
typedef types<T, Arg> free_args_list;
typedef meta::tuple_types<R> returns_list;
typedef R(function_type)(T&, R);
typedef R(*function_pointer_type)(T&, R);
@ -6563,11 +6564,20 @@ namespace sol {
template <typename T>
struct protect_t {
T value;
template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler>
protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {}
protect_t(const protect_t&) = default;
protect_t(protect_t&&) = default;
protect_t& operator=(const protect_t&) = default;
protect_t& operator=(protect_t&&) = default;
};
template <typename T>
auto protect(T&& value) {
return protect_t<std::decay_t<T>>{ std::forward<T>(value) };
return protect_t<std::decay_t<T>>(std::forward<T>(value));
}
} // sol
@ -6755,101 +6765,116 @@ namespace sol {
return 1;
}
template <typename F, bool is_index, bool is_variable, bool checked, typename = void>
template <typename F, bool is_index, bool is_variable, bool checked, int boost, typename = void>
struct agnostic_lua_call_wrapper {
static int var_call(std::true_type, lua_State* L, F& f) {
template <typename Fx>
static int var_call(std::true_type, lua_State* L, Fx&& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::returns_list returns_list;
typedef typename wrap::free_args_list args_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_index ? 1 : 2, checked>(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f);
return stack::call_into_lua<is_index ? 1 : 2, checked>(returns_list(), args_list(), L, boost + ( is_index ? 2 : 3 ), caller(), std::forward<Fx>(f));
}
static int var_call(std::false_type, lua_State* L, F& f) {
template <typename Fx>
static int var_call(std::false_type, lua_State* L, Fx&& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::free_args_list args_list;
typedef typename wrap::returns_list returns_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<0, checked>(returns_list(), args_list(), L, 1, caller(), f);
return stack::call_into_lua<0, checked>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f));
}
static int call(lua_State* L, F& f) {
return var_call(std::integral_constant<bool, is_variable>(), L, f);
template <typename Fx>
static int call(lua_State* L, Fx&& f) {
return var_call(std::integral_constant<bool, is_variable>(), L, std::forward<Fx>(f));
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, lua_r_CFunction f) {
return f(L);
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, lua_CFunction f) {
return f(L);
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, const no_prop&) {
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, const no_construction&) {
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
}
};
template <typename... Args, bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, C> {
template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, C> {
static int call(lua_State*, const bases<Args...>&) {
// Uh. How did you even call this, lul
return 0;
}
};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked> {};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {};
template <typename T, typename F, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, is_index, is_variable, checked, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
static int call(lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, is_index, is_variable, checked, boost, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
template <typename Fx>
static int call(lua_State* L, Fx&& f, object_type& o) {
typedef typename wrap::returns_list returns_list;
typedef typename wrap::args_list args_list;
typedef typename wrap::caller caller;
typedef typename wrap::object_type object_type;
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward<Fx>(f), o);
}
template <typename Fx>
static int call(lua_State* L, Fx&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
}
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
return call(L, std::forward<Fx>(f), *o);
#else
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
return call(L, std::forward<Fx>(f), o);
#endif // Safety
}
};
template <typename T, typename F, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, false, is_variable, checked, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
template <typename T, typename F, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, false, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
typedef sol::lua_bind_traits<F> traits_type;
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
static int call_assign(std::true_type, lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
template <typename V>
static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) {
typedef typename wrap::args_list args_list;
typedef typename wrap::object_type object_type;
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o);
}
template <typename V>
static int call_assign(std::true_type, lua_State* L, V&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
@ -6858,58 +6883,74 @@ namespace sol {
}
return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
}
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
return call_assign(std::true_type(), L, f, *o);
#else
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
return call_assign(std::true_type(), L, f, o);
#endif // Safety
}
static int call_assign(std::false_type, lua_State* L, F&) {
template <typename... Args>
static int call_assign(std::false_type, lua_State* L, Args&&...) {
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
}
static int call_const(std::false_type, lua_State* L, F& f) {
template <typename... Args>
static int call_const(std::false_type, lua_State* L, Args&&... args) {
typedef typename traits_type::return_type R;
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...);
}
static int call_const(std::true_type, lua_State* L, F&) {
template <typename... Args>
static int call_const(std::true_type, lua_State* L, Args&&...) {
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
}
static int call(lua_State* L, F& f) {
template <typename V>
static int call(lua_State* L, V&& f) {
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
}
template <typename V>
static int call(lua_State* L, V&& f, object_type& o) {
return call_const(std::is_const<typename traits_type::return_type>(), L, f, o);
}
};
template <typename T, typename F, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, true, is_variable, checked, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
template <typename T, typename F, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, true, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
typedef sol::lua_bind_traits<F> traits_type;
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
static int call(lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
template <typename V>
static int call(lua_State* L, V&& f, object_type& o) {
typedef typename wrap::returns_list returns_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o);
}
template <typename V>
static int call(lua_State* L, V&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<T*>(L, 1));
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
if (is_variable) {
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
}
return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)");
}
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
return call(L, f, *o);
#else
object_type& o = static_cast<object_type&>(stack::get<T&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return call(L, f, o);
#endif // Safety
}
};
template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, checked, C> {
template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, checked, boost, C> {
typedef sol::constructor_list<Args...> F;
static int call(lua_State* L, F&) {
@ -6924,7 +6965,7 @@ namespace sol {
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
referencepointer = obj;
construct_match<T, Args...>(constructor_match<T, 1>(obj), L, argcount, 1 + static_cast<int>(syntax));
construct_match<T, Args...>(constructor_match<T, 1>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
userdataref.push();
luaL_getmetatable(L, &metakey[0]);
@ -6938,8 +6979,8 @@ namespace sol {
}
};
template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, checked, C> {
template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, C> {
typedef sol::constructor_wrapper<Cxs...> F;
struct onmatch {
@ -6953,7 +6994,7 @@ namespace sol {
referencepointer = obj;
auto& func = std::get<I>(f.set);
stack::call_into_lua<1, checked>(r, a, L, start, func, detail::implicit_wrapper<T>(obj));
stack::call_into_lua<1, checked>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
userdataref.push();
luaL_getmetatable(L, &metakey[0]);
@ -6978,8 +7019,8 @@ namespace sol {
};
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, std::enable_if_t<std::is_void<Fx>::value>> {
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<std::is_void<Fx>::value>> {
typedef sol::destructor_wrapper<Fx> F;
static int call(lua_State* L, const F&) {
@ -6987,8 +7028,8 @@ namespace sol {
}
};
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, std::enable_if_t<!std::is_void<Fx>::value>> {
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<!std::is_void<Fx>::value>> {
typedef sol::destructor_wrapper<Fx> F;
static int call(lua_State* L, const F& f) {
@ -6998,8 +7039,8 @@ namespace sol {
}
};
template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, C> {
template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, C> {
typedef overload_set<Fs...> F;
struct on_match {
@ -7015,18 +7056,19 @@ namespace sol {
}
};
template <typename T, typename V, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, C> {
template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, C> {
typedef protect_t<V> F;
static int call(lua_State* L, F& fx) {
return lua_call_wrapper<T, V, is_index, is_variable, true>{}.call(L, fx.value);
template <typename... Args>
static int call(lua_State* L, F& fx, Args&&... args) {
return lua_call_wrapper<T, V, is_index, is_variable, true, boost>{}.call(L, fx.value, std::forward<Args>(args)...);
}
};
template <typename T, bool is_index, bool is_variable, typename Fx>
inline int call_wrapped(lua_State* L, Fx&& fx) {
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
template <typename T, bool is_index, bool is_variable, int boost = 0, typename Fx, typename... Args>
inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
}
template <typename T, bool is_index, bool is_variable, typename F>
@ -7191,16 +7233,15 @@ namespace sol {
static int real_call(lua_State* L) {
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
function_type* fx = udata.first;
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
return r;
function_type* f = udata.first;
return call_detail::call_wrapped<void, false, false>(L, f);
}
static int call(lua_State* L) {
return detail::static_trampoline<(&real_call)>(L);
}
int operator()(lua_State* L) {
int operator()(lua_State* L) const {
return call(L);
}
};
@ -7220,10 +7261,7 @@ namespace sol {
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
function_type& memfx = memberdata.first;
auto& item = *objdata.first;
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
return (item.*memfx)(std::forward<decltype(args)>(args)...);
};
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
return call_detail::call_wrapped<T, false, false, -1>(L, memfx, item);
}
static int call(lua_State* L) {
@ -7235,30 +7273,6 @@ namespace sol {
}
};
template <int N, typename R, typename M, typename V>
int set_assignable(std::false_type, lua_State* L, M&, V&) {
lua_pop(L, N);
return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available");
}
template <int N, typename R, typename M, typename V>
int set_assignable(std::true_type, lua_State* L, M& mem, V& var) {
(mem.*var) = stack::get<R>(L, N);
lua_pop(L, N);
return 0;
}
template <int N, typename R, typename M, typename V>
int set_variable(std::true_type, lua_State* L, M& mem, V& var) {
return set_assignable<N, R>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, mem, var);
}
template <int N, typename R, typename M, typename V>
int set_variable(std::false_type, lua_State* L, M&, V&) {
lua_pop(L, N);
return luaL_error(L, "sol: cannot write to a const variable");
}
template<typename T, typename Function>
struct upvalue_member_variable {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
@ -7276,11 +7290,9 @@ namespace sol {
function_type& var = memberdata.first;
switch (lua_gettop(L)) {
case 0:
stack::push(L, (mem.*var));
return 1;
return call_detail::call_wrapped<T, true, false, -1>(L, var, mem);
case 1:
set_variable<1, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
return 0;
return call_detail::call_wrapped<T, false, false, -1>(L, var, mem);
default:
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
}
@ -7326,16 +7338,12 @@ namespace sol {
// Layout:
// idx 1...n: verbatim data of member variable pointer
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
auto& mem = stack::get<T>(L, 1);
function_type& var = memberdata.first;
switch (lua_gettop(L)) {
case 1:
lua_pop(L, 1);
stack::push(L, (mem.*var));
return 1;
return call_detail::call_wrapped<T, true, false>(L, var);
case 2:
set_variable<2, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
return 0;
return call_detail::call_wrapped<T, false, false>(L, var);
default:
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
}
@ -7590,44 +7598,6 @@ namespace sol {
}
namespace stack {
template <typename F, typename G>
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
static int push(lua_State* L, property_wrapper<F, G> pw) {
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
}
};
template <typename F>
struct pusher<property_wrapper<F, void>> {
static int push(lua_State* L, property_wrapper<F, void> pw) {
return stack::push(L, std::move(pw.read));
}
};
template <typename F>
struct pusher<property_wrapper<void, F>> {
static int push(lua_State* L, property_wrapper<void, F> pw) {
return stack::push(L, std::move(pw.write));
}
};
template <typename T, typename... Lists>
struct pusher<detail::constructors_for<T, constructor_list<Lists...>>> {
static int push(lua_State* L, detail::constructors_for<T, constructor_list<Lists...>>) {
lua_CFunction cf = call_detail::construct<T, Lists...>;
return stack::push(L, cf);
}
};
template <typename T, typename... Fxs>
struct pusher<detail::constructors_for<T, constructor_wrapper<Fxs...>>> {
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
lua_CFunction cf = call_detail::call_user<T, false, false>;
int closures = stack::push(L, make_user(std::move(c)));
return stack::push(L, c_closure(cf, closures));
}
};
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
template <typename... Sig, typename Fx, typename... Args>
@ -7824,6 +7794,68 @@ namespace sol {
}
};
template <typename T>
struct pusher<protect_t<T>> {
static int push(lua_State* L, protect_t<T>&& pw) {
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value));
return stack::push(L, c_closure(cf, closures));
}
static int push(lua_State* L, const protect_t<T>& pw) {
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
int closures = stack::push<user<protect_t<T>>>(L, pw.value);
return stack::push(L, c_closure(cf, closures));
}
};
template <typename F, typename G>
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
}
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
return stack::push(L, sol::overload(pw.read, pw.write));
}
};
template <typename F>
struct pusher<property_wrapper<F, void>> {
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
return stack::push(L, std::move(pw.read));
}
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
return stack::push(L, pw.read);
}
};
template <typename F>
struct pusher<property_wrapper<void, F>> {
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
return stack::push(L, std::move(pw.write));
}
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
return stack::push(L, pw.write);
}
};
template <typename T, typename... Lists>
struct pusher<detail::constructors_for<T, constructor_list<Lists...>>> {
static int push(lua_State* L, detail::constructors_for<T, constructor_list<Lists...>>) {
lua_CFunction cf = call_detail::construct<T, Lists...>;
return stack::push(L, cf);
}
};
template <typename T, typename... Fxs>
struct pusher<detail::constructors_for<T, constructor_wrapper<Fxs...>>> {
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
int closures = stack::push<user<T>>(L, std::move(c));
return stack::push(L, c_closure(cf, closures));
}
};
} // stack
} // sol
@ -9173,24 +9205,25 @@ namespace sol {
}
template<typename... Args>
simple_usertype_metatable(usertype_detail::verified_tag v, lua_State* L, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
template<typename... Args>
simple_usertype_metatable(usertype_detail::add_destructor_tag, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::verified, L, std::forward<Args>(args)..., "__gc", default_destructor) {}
simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {}
template<typename... Args>
simple_usertype_metatable(usertype_detail::check_destructor_tag, lua_State* L, Args&&... args) : simple_usertype_metatable(meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), L, std::forward<Args>(args)...) {}
simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {}
public:
simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(meta::condition<meta::all<std::is_default_constructible<T>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), L) {}
template<typename... Args>
simple_usertype_metatable(lua_State* L, Args&&... args) : simple_usertype_metatable(meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), L, std::forward<Args>(args)...) {}
template<typename Arg, typename... Args, meta::disable<meta::is_specialization_of<constructors, meta::unqualified_t<Arg>>, meta::is_specialization_of<constructor_wrapper, meta::unqualified_t<Arg>>> = meta::enabler>
simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Arg>(arg), std::forward<Args>(args)...) {}
template<typename... Args, typename... CArgs>
simple_usertype_metatable(constructors<CArgs...> constructorlist, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::check_destructor_tag(), L, std::forward<Args>(args)..., "new", constructorlist) {}
simple_usertype_metatable(lua_State* L, constructors<CArgs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {}
template<typename... Args, typename... Fxs>
simple_usertype_metatable(constructor_wrapper<Fxs...> constructorlist, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::check_destructor_tag(), L, std::forward<Args>(args)..., "new", constructorlist) {}
simple_usertype_metatable(lua_State* L, constructor_wrapper<Fxs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {}
virtual int push_um(lua_State* L) override {
return stack::push(L, std::move(*this));

View File

@ -215,6 +215,7 @@ namespace sol {
typedef std::tuple<Arg> args_tuple;
typedef R return_type;
typedef types<Arg> args_list;
typedef types<T, Arg> free_args_list;
typedef meta::tuple_types<R> returns_list;
typedef R(function_type)(T&, R);
typedef R(*function_pointer_type)(T&, R);

View File

@ -144,101 +144,116 @@ namespace sol {
return 1;
}
template <typename F, bool is_index, bool is_variable, bool checked, typename = void>
template <typename F, bool is_index, bool is_variable, bool checked, int boost, typename = void>
struct agnostic_lua_call_wrapper {
static int var_call(std::true_type, lua_State* L, F& f) {
template <typename Fx>
static int var_call(std::true_type, lua_State* L, Fx&& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::returns_list returns_list;
typedef typename wrap::free_args_list args_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_index ? 1 : 2, checked>(returns_list(), args_list(), L, is_index ? 2 : 3, caller(), f);
return stack::call_into_lua<is_index ? 1 : 2, checked>(returns_list(), args_list(), L, boost + ( is_index ? 2 : 3 ), caller(), std::forward<Fx>(f));
}
static int var_call(std::false_type, lua_State* L, F& f) {
template <typename Fx>
static int var_call(std::false_type, lua_State* L, Fx&& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::free_args_list args_list;
typedef typename wrap::returns_list returns_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<0, checked>(returns_list(), args_list(), L, 1, caller(), f);
return stack::call_into_lua<0, checked>(returns_list(), args_list(), L, boost + 1, caller(), std::forward<Fx>(f));
}
static int call(lua_State* L, F& f) {
return var_call(std::integral_constant<bool, is_variable>(), L, f);
template <typename Fx>
static int call(lua_State* L, Fx&& f) {
return var_call(std::integral_constant<bool, is_variable>(), L, std::forward<Fx>(f));
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, lua_r_CFunction f) {
return f(L);
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<lua_CFunction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, lua_CFunction f) {
return f(L);
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<no_prop, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, const no_prop&) {
return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property");
}
};
template <bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, C> {
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<no_construction, is_index, is_variable, checked, boost, C> {
static int call(lua_State* L, const no_construction&) {
return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)");
}
};
template <typename... Args, bool is_index, bool is_variable, bool checked, typename C>
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, C> {
template <typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct agnostic_lua_call_wrapper<bases<Args...>, is_index, is_variable, checked, boost, C> {
static int call(lua_State*, const bases<Args...>&) {
// Uh. How did you even call this, lul
return 0;
}
};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked> {};
template <typename T, typename F, bool is_index, bool is_variable, bool checked = stack::stack_detail::default_check_arguments, int boost = 0, typename = void>
struct lua_call_wrapper : agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost> {};
template <typename T, typename F, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, is_index, is_variable, checked, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
static int call(lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, is_index, is_variable, checked, boost, std::enable_if_t<std::is_member_function_pointer<F>::value>> {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
template <typename Fx>
static int call(lua_State* L, Fx&& f, object_type& o) {
typedef typename wrap::returns_list returns_list;
typedef typename wrap::args_list args_list;
typedef typename wrap::caller caller;
typedef typename wrap::object_type object_type;
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward<Fx>(f), o);
}
template <typename Fx>
static int call(lua_State* L, Fx&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
return luaL_error(L, "sol: received null for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)");
}
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
return call(L, std::forward<Fx>(f), *o);
#else
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
return call(L, std::forward<Fx>(f), o);
#endif // Safety
}
};
template <typename T, typename F, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, false, is_variable, checked, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
template <typename T, typename F, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, false, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
typedef sol::lua_bind_traits<F> traits_type;
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
static int call_assign(std::true_type, lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
template <typename V>
static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) {
typedef typename wrap::args_list args_list;
typedef typename wrap::object_type object_type;
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o);
}
template <typename V>
static int call_assign(std::true_type, lua_State* L, V&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
@ -247,58 +262,74 @@ namespace sol {
}
return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)");
}
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, *o);
return call_assign(std::true_type(), L, f, *o);
#else
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1>(types<void>(), args_list(), L, is_variable ? 3 : 2, caller(), f, o);
return call_assign(std::true_type(), L, f, o);
#endif // Safety
}
static int call_assign(std::false_type, lua_State* L, F&) {
template <typename... Args>
static int call_assign(std::false_type, lua_State* L, Args&&...) {
return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available");
}
static int call_const(std::false_type, lua_State* L, F& f) {
template <typename... Args>
static int call_const(std::false_type, lua_State* L, Args&&... args) {
typedef typename traits_type::return_type R;
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, f);
return call_assign(std::is_assignable<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>(), L, std::forward<Args>(args)...);
}
static int call_const(std::true_type, lua_State* L, F&) {
template <typename... Args>
static int call_const(std::true_type, lua_State* L, Args&&...) {
return luaL_error(L, "sol: cannot write to a readonly (const) variable");
}
static int call(lua_State* L, F& f) {
template <typename V>
static int call(lua_State* L, V&& f) {
return call_const(std::is_const<typename traits_type::return_type>(), L, f);
}
template <typename V>
static int call(lua_State* L, V&& f, object_type& o) {
return call_const(std::is_const<typename traits_type::return_type>(), L, f, o);
}
};
template <typename T, typename F, bool is_variable, bool checked>
struct lua_call_wrapper<T, F, true, is_variable, checked, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
template <typename T, typename F, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, F, true, is_variable, checked, boost, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
typedef sol::lua_bind_traits<F> traits_type;
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
static int call(lua_State* L, F& f) {
typedef wrapper<meta::unqualified_t<F>> wrap;
typedef typename wrap::object_type object_type;
template <typename V>
static int call(lua_State* L, V&& f, object_type& o) {
typedef typename wrap::returns_list returns_list;
typedef typename wrap::caller caller;
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o);
}
template <typename V>
static int call(lua_State* L, V&& f) {
typedef std::conditional_t<std::is_void<T>::value, object_type, T> Ta;
#ifdef SOL_SAFE_USERTYPE
object_type* o = static_cast<object_type*>(stack::get<T*>(L, 1));
object_type* o = static_cast<object_type*>(stack::get<Ta*>(L, 1));
if (o == nullptr) {
if (is_variable) {
return luaL_error(L, "sol: 'self' argument is nil (bad '.' access?)");
}
return luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument)");
}
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, *o);
return call(L, f, *o);
#else
object_type& o = static_cast<object_type&>(stack::get<T&>(L, 1));
return stack::call_into_lua<is_variable ? 2 : 1, checked>(returns_list(), types<>(), L, is_variable ? 3 : 2, caller(), f, o);
object_type& o = static_cast<object_type&>(stack::get<Ta&>(L, 1));
return call(L, f, o);
#endif // Safety
}
};
template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, checked, C> {
template <typename T, typename... Args, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, sol::constructor_list<Args...>, is_index, is_variable, checked, boost, C> {
typedef sol::constructor_list<Args...> F;
static int call(lua_State* L, F&) {
@ -313,7 +344,7 @@ namespace sol {
T* obj = reinterpret_cast<T*>(pointerpointer + 1);
referencepointer = obj;
construct_match<T, Args...>(constructor_match<T, 1>(obj), L, argcount, 1 + static_cast<int>(syntax));
construct_match<T, Args...>(constructor_match<T, 1>(obj), L, argcount, boost + 1 + static_cast<int>(syntax));
userdataref.push();
luaL_getmetatable(L, &metakey[0]);
@ -327,8 +358,8 @@ namespace sol {
}
};
template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, checked, C> {
template <typename T, typename... Cxs, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, sol::constructor_wrapper<Cxs...>, is_index, is_variable, checked, boost, C> {
typedef sol::constructor_wrapper<Cxs...> F;
struct onmatch {
@ -342,7 +373,7 @@ namespace sol {
referencepointer = obj;
auto& func = std::get<I>(f.set);
stack::call_into_lua<1, checked>(r, a, L, start, func, detail::implicit_wrapper<T>(obj));
stack::call_into_lua<1, checked>(r, a, L, boost + start, func, detail::implicit_wrapper<T>(obj));
userdataref.push();
luaL_getmetatable(L, &metakey[0]);
@ -367,8 +398,8 @@ namespace sol {
};
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, std::enable_if_t<std::is_void<Fx>::value>> {
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<std::is_void<Fx>::value>> {
typedef sol::destructor_wrapper<Fx> F;
static int call(lua_State* L, const F&) {
@ -376,8 +407,8 @@ namespace sol {
}
};
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, std::enable_if_t<!std::is_void<Fx>::value>> {
template <typename T, typename Fx, bool is_index, bool is_variable, bool checked, int boost>
struct lua_call_wrapper<T, sol::destructor_wrapper<Fx>, is_index, is_variable, checked, boost, std::enable_if_t<!std::is_void<Fx>::value>> {
typedef sol::destructor_wrapper<Fx> F;
static int call(lua_State* L, const F& f) {
@ -387,8 +418,8 @@ namespace sol {
}
};
template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, C> {
template <typename T, typename... Fs, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, overload_set<Fs...>, is_index, is_variable, checked, boost, C> {
typedef overload_set<Fs...> F;
struct on_match {
@ -404,18 +435,19 @@ namespace sol {
}
};
template <typename T, typename V, bool is_index, bool is_variable, bool checked, typename C>
struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, C> {
template <typename T, typename V, bool is_index, bool is_variable, bool checked, int boost, typename C>
struct lua_call_wrapper<T, protect_t<V>, is_index, is_variable, checked, boost, C> {
typedef protect_t<V> F;
static int call(lua_State* L, F& fx) {
return lua_call_wrapper<T, V, is_index, is_variable, true>{}.call(L, fx.value);
template <typename... Args>
static int call(lua_State* L, F& fx, Args&&... args) {
return lua_call_wrapper<T, V, is_index, is_variable, true, boost>{}.call(L, fx.value, std::forward<Args>(args)...);
}
};
template <typename T, bool is_index, bool is_variable, typename Fx>
inline int call_wrapped(lua_State* L, Fx&& fx) {
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable>{}.call(L, std::forward<Fx>(fx));
template <typename T, bool is_index, bool is_variable, int boost = 0, typename Fx, typename... Args>
inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) {
return lua_call_wrapper<T, meta::unqualified_t<Fx>, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
}
template <typename T, bool is_index, bool is_variable, typename F>

View File

@ -44,44 +44,6 @@ namespace sol {
}
namespace stack {
template <typename F, typename G>
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
static int push(lua_State* L, property_wrapper<F, G> pw) {
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
}
};
template <typename F>
struct pusher<property_wrapper<F, void>> {
static int push(lua_State* L, property_wrapper<F, void> pw) {
return stack::push(L, std::move(pw.read));
}
};
template <typename F>
struct pusher<property_wrapper<void, F>> {
static int push(lua_State* L, property_wrapper<void, F> pw) {
return stack::push(L, std::move(pw.write));
}
};
template <typename T, typename... Lists>
struct pusher<detail::constructors_for<T, constructor_list<Lists...>>> {
static int push(lua_State* L, detail::constructors_for<T, constructor_list<Lists...>>) {
lua_CFunction cf = call_detail::construct<T, Lists...>;
return stack::push(L, cf);
}
};
template <typename T, typename... Fxs>
struct pusher<detail::constructors_for<T, constructor_wrapper<Fxs...>>> {
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
lua_CFunction cf = call_detail::call_user<T, false, false>;
int closures = stack::push(L, make_user(std::move(c)));
return stack::push(L, c_closure(cf, closures));
}
};
template<typename... Sigs>
struct pusher<function_sig<Sigs...>> {
template <typename... Sig, typename Fx, typename... Args>
@ -278,6 +240,68 @@ namespace sol {
}
};
template <typename T>
struct pusher<protect_t<T>> {
static int push(lua_State* L, protect_t<T>&& pw) {
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
int closures = stack::push<user<protect_t<T>>>(L, std::move(pw.value));
return stack::push(L, c_closure(cf, closures));
}
static int push(lua_State* L, const protect_t<T>& pw) {
lua_CFunction cf = call_detail::call_user<void, false, false, protect_t<T>>;
int closures = stack::push<user<protect_t<T>>>(L, pw.value);
return stack::push(L, c_closure(cf, closures));
}
};
template <typename F, typename G>
struct pusher<property_wrapper<F, G>, std::enable_if_t<!std::is_void<F>::value && !std::is_void<G>::value>> {
static int push(lua_State* L, property_wrapper<F, G>&& pw) {
return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write)));
}
static int push(lua_State* L, const property_wrapper<F, G>& pw) {
return stack::push(L, sol::overload(pw.read, pw.write));
}
};
template <typename F>
struct pusher<property_wrapper<F, void>> {
static int push(lua_State* L, property_wrapper<F, void>&& pw) {
return stack::push(L, std::move(pw.read));
}
static int push(lua_State* L, const property_wrapper<F, void>& pw) {
return stack::push(L, pw.read);
}
};
template <typename F>
struct pusher<property_wrapper<void, F>> {
static int push(lua_State* L, property_wrapper<void, F>&& pw) {
return stack::push(L, std::move(pw.write));
}
static int push(lua_State* L, const property_wrapper<void, F>& pw) {
return stack::push(L, pw.write);
}
};
template <typename T, typename... Lists>
struct pusher<detail::constructors_for<T, constructor_list<Lists...>>> {
static int push(lua_State* L, detail::constructors_for<T, constructor_list<Lists...>>) {
lua_CFunction cf = call_detail::construct<T, Lists...>;
return stack::push(L, cf);
}
};
template <typename T, typename... Fxs>
struct pusher<detail::constructors_for<T, constructor_wrapper<Fxs...>>> {
static int push(lua_State* L, constructor_wrapper<Fxs...> c) {
lua_CFunction cf = call_detail::call_user<T, false, false, constructor_wrapper<Fxs...>>;
int closures = stack::push<user<T>>(L, std::move(c));
return stack::push(L, c_closure(cf, closures));
}
};
} // stack
} // sol

View File

@ -33,16 +33,15 @@ namespace sol {
static int real_call(lua_State* L) {
auto udata = stack::stack_detail::get_as_upvalues<function_type*>(L);
function_type* fx = udata.first;
int r = stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
return r;
function_type* f = udata.first;
return call_detail::call_wrapped<void, false, false>(L, f);
}
static int call(lua_State* L) {
return detail::static_trampoline<(&real_call)>(L);
}
int operator()(lua_State* L) {
int operator()(lua_State* L) const {
return call(L);
}
};
@ -62,10 +61,7 @@ namespace sol {
auto objdata = stack::stack_detail::get_as_upvalues<T*>(L, memberdata.second);
function_type& memfx = memberdata.first;
auto& item = *objdata.first;
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type {
return (item.*memfx)(std::forward<decltype(args)>(args)...);
};
return stack::call_into_lua(meta::tuple_types<typename traits_type::return_type>(), typename traits_type::args_list(), L, 1, fx);
return call_detail::call_wrapped<T, false, false, -1>(L, memfx, item);
}
static int call(lua_State* L) {
@ -77,30 +73,6 @@ namespace sol {
}
};
template <int N, typename R, typename M, typename V>
int set_assignable(std::false_type, lua_State* L, M&, V&) {
lua_pop(L, N);
return luaL_error(L, "sol: cannot write to this type: copy assignment/constructor not available");
}
template <int N, typename R, typename M, typename V>
int set_assignable(std::true_type, lua_State* L, M& mem, V& var) {
(mem.*var) = stack::get<R>(L, N);
lua_pop(L, N);
return 0;
}
template <int N, typename R, typename M, typename V>
int set_variable(std::true_type, lua_State* L, M& mem, V& var) {
return set_assignable<N, R>(std::is_assignable<std::add_lvalue_reference_t<R>, R>(), L, mem, var);
}
template <int N, typename R, typename M, typename V>
int set_variable(std::false_type, lua_State* L, M&, V&) {
lua_pop(L, N);
return luaL_error(L, "sol: cannot write to a const variable");
}
template<typename T, typename Function>
struct upvalue_member_variable {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
@ -118,11 +90,9 @@ namespace sol {
function_type& var = memberdata.first;
switch (lua_gettop(L)) {
case 0:
stack::push(L, (mem.*var));
return 1;
return call_detail::call_wrapped<T, true, false, -1>(L, var, mem);
case 1:
set_variable<1, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
return 0;
return call_detail::call_wrapped<T, false, false, -1>(L, var, mem);
default:
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
}
@ -168,16 +138,12 @@ namespace sol {
// Layout:
// idx 1...n: verbatim data of member variable pointer
auto memberdata = stack::stack_detail::get_as_upvalues<function_type>(L, 1);
auto& mem = stack::get<T>(L, 1);
function_type& var = memberdata.first;
switch (lua_gettop(L)) {
case 1:
lua_pop(L, 1);
stack::push(L, (mem.*var));
return 1;
return call_detail::call_wrapped<T, true, false>(L, var);
case 2:
set_variable<2, typename traits_type::return_type>(meta::neg<std::is_const<typename traits_type::return_type>>(), L, mem, var);
return 0;
return call_detail::call_wrapped<T, false, false>(L, var);
default:
return luaL_error(L, "sol: incorrect number of arguments to member variable function");
}

View File

@ -22,6 +22,7 @@
#ifndef SOL_PROTECT_HPP
#define SOL_PROTECT_HPP
#include "traits.hpp"
#include <utility>
namespace sol {
@ -29,11 +30,20 @@ namespace sol {
template <typename T>
struct protect_t {
T value;
template <typename Arg, typename... Args, meta::disable<std::is_same<protect_t, meta::unqualified_t<Arg>>> = meta::enabler>
protect_t(Arg&& arg, Args&&... args) : value(std::forward<Arg>(arg), std::forward<Args>(args)...) {}
protect_t(const protect_t&) = default;
protect_t(protect_t&&) = default;
protect_t& operator=(const protect_t&) = default;
protect_t& operator=(protect_t&&) = default;
};
template <typename T>
auto protect(T&& value) {
return protect_t<std::decay_t<T>>{ std::forward<T>(value) };
return protect_t<std::decay_t<T>>(std::forward<T>(value));
}
} // sol

View File

@ -66,24 +66,33 @@ namespace sol {
}
template<typename... Args>
simple_usertype_metatable(usertype_detail::verified_tag v, lua_State* L, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
template<typename... Args>
simple_usertype_metatable(usertype_detail::add_destructor_tag, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::verified, L, std::forward<Args>(args)..., "__gc", default_destructor) {}
simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward<Args>(args)..., "__gc", default_destructor) {}
template<typename... Args>
simple_usertype_metatable(usertype_detail::check_destructor_tag, lua_State* L, Args&&... args) : simple_usertype_metatable(meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), L, std::forward<Args>(args)...) {}
simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_destructible<T>, meta::neg<usertype_detail::has_destructor<Args...>>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward<Args>(args)...) {}
public:
simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(meta::condition<meta::all<std::is_default_constructible<T>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), L) {}
template<typename... Args>
simple_usertype_metatable(lua_State* L, Args&&... args) : simple_usertype_metatable(meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), L, std::forward<Args>(args)...) {}
template<typename Arg, typename... Args, meta::disable_any<
meta::any_same<meta::unqualified_t<Arg>,
usertype_detail::verified_tag,
usertype_detail::add_destructor_tag,
usertype_detail::check_destructor_tag
>,
meta::is_specialization_of<constructors, meta::unqualified_t<Arg>>,
meta::is_specialization_of<constructor_wrapper, meta::unqualified_t<Arg>>
> = meta::enabler>
simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition<meta::all<std::is_default_constructible<T>, meta::neg<usertype_detail::has_constructor<Args...>>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward<Arg>(arg), std::forward<Args>(args)...) {}
template<typename... Args, typename... CArgs>
simple_usertype_metatable(constructors<CArgs...> constructorlist, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::check_destructor_tag(), L, std::forward<Args>(args)..., "new", constructorlist) {}
simple_usertype_metatable(lua_State* L, constructors<CArgs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {}
template<typename... Args, typename... Fxs>
simple_usertype_metatable(constructor_wrapper<Fxs...> constructorlist, lua_State* L, Args&&... args) : simple_usertype_metatable(usertype_detail::check_destructor_tag(), L, std::forward<Args>(args)..., "new", constructorlist) {}
simple_usertype_metatable(lua_State* L, constructor_wrapper<Fxs...> constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward<Args>(args)..., "new", constructorlist) {}
virtual int push_um(lua_State* L) override {
return stack::push(L, std::move(*this));

View File

@ -133,6 +133,9 @@ namespace sol {
template<typename... Args>
using disable = std::enable_if_t<neg<all<Args...>>::value, enable_t>;
template<typename... Args>
using disable_any = std::enable_if_t<neg<any<Args...>>::value, enable_t>;
template<typename V, typename... Vs>
struct find_in_pack_v : boolean<false> { };

View File

@ -816,7 +816,10 @@ TEST_CASE("functions/variadic_args", "Check to see we can receive multiple argum
TEST_CASE("functions/required_and_variadic_args", "Check if a certain number of arguments can still be required even when using variadic_args") {
sol::state lua;
lua.set_function("v", [](sol::this_state, sol::variadic_args, int, int) {});
lua.set_function("v",
[](sol::this_state, sol::variadic_args, int, int) {
}
);
REQUIRE_NOTHROW(lua.script("v(20, 25, 30)"));
REQUIRE_NOTHROW(lua.script("v(20, 25)"));
REQUIRE_THROWS(lua.script("v(20)"));

View File

@ -1,85 +0,0 @@
#define SOL_CHECK_ARGUMENTS
#include <sol.hpp>
#include <catch.hpp>
#include <iostream>
#include <mutex>
TEST_CASE("usertypes/simple_usertypes", "Ensure that simple usertypes properly work here") {
struct marker {
bool value = false;
};
struct bark {
int var = 50;
marker mark;
void fun() {
var = 51;
}
int get() const {
return var;
}
int set(int x) {
var = x;
return var;
}
std::string special() const {
return mark.value ? "woof" : "pantpant";
}
const marker& the_marker() const {
return mark;
}
};
sol::state lua;
lua.new_simple_usertype<bark>("bark",
"fun", &bark::fun,
"get", &bark::get,
"var", &bark::var,
"the_marker", &bark::the_marker,
"x", sol::property(&bark::get),
"y", sol::property(&bark::set),
"z", sol::property(&bark::get, &bark::set)
);
lua.script("b = bark.new()");
bark& b = lua["b"];
lua.script("b:fun()");
int var = b.var;
REQUIRE(var == 51);
lua.script("b:var(20)");
lua.script("v = b:var()");
int v = lua["v"];
REQUIRE(v == 20);
lua.script("m = b:the_marker()");
marker& m = lua["m"];
REQUIRE_FALSE(b.mark.value);
REQUIRE_FALSE(m.value);
m.value = true;
REQUIRE(&b.mark == &m);
REQUIRE(b.mark.value);
sol::table barktable = lua["bark"];
barktable["special"] = &bark::special;
lua.script("s = b:special()");
std::string s = lua["s"];
REQUIRE(s == "woof");
lua.script("b:y(24)");
lua.script("x = b:x()");
int x = lua["x"];
REQUIRE(x == 24);
lua.script("z = b:z(b:z() + 5)");
int z = lua["z"];
REQUIRE(z == 29);
}

172
test_simple_usertypes.cpp Normal file
View File

@ -0,0 +1,172 @@
#define SOL_CHECK_ARGUMENTS
#include <sol.hpp>
#include <catch.hpp>
#include <iostream>
#include <mutex>
TEST_CASE("usertypes/simple_usertypes", "Ensure that simple usertypes properly work here") {
struct marker {
bool value = false;
};
struct bark {
int var = 50;
marker mark;
void fun() {
var = 51;
}
int get() const {
return var;
}
int set(int x) {
var = x;
return var;
}
std::string special() const {
return mark.value ? "woof" : "pantpant";
}
const marker& the_marker() const {
return mark;
}
};
sol::state lua;
lua.new_simple_usertype<bark>("bark",
"fun", &bark::fun,
"get", &bark::get,
"var", &bark::var,
"the_marker", &bark::the_marker,
"x", sol::property(&bark::get),
"y", sol::property(&bark::set),
"z", sol::property(&bark::get, &bark::set)
);
lua.script("b = bark.new()");
bark& b = lua["b"];
lua.script("b:fun()");
int var = b.var;
REQUIRE(var == 51);
lua.script("b:var(20)");
lua.script("v = b:var()");
int v = lua["v"];
REQUIRE(v == 20);
lua.script("m = b:the_marker()");
marker& m = lua["m"];
REQUIRE_FALSE(b.mark.value);
REQUIRE_FALSE(m.value);
m.value = true;
REQUIRE(&b.mark == &m);
REQUIRE(b.mark.value);
sol::table barktable = lua["bark"];
barktable["special"] = &bark::special;
lua.script("s = b:special()");
std::string s = lua["s"];
REQUIRE(s == "woof");
lua.script("b:y(24)");
lua.script("x = b:x()");
int x = lua["x"];
REQUIRE(x == 24);
lua.script("z = b:z(b:z() + 5)");
int z = lua["z"];
REQUIRE(z == 29);
}
TEST_CASE("usertypes/simple-usertypes-constructors", "Ensure that calls with specific arguments work") {
struct marker {
bool value = false;
};
struct bark {
int var = 50;
marker mark;
bark() {}
bark(int v) : var(v) {}
void fun() {
var = 51;
}
int get() const {
return var;
}
int set(int x) {
var = x;
return var;
}
std::string special() const {
return mark.value ? "woof" : "pantpant";
}
const marker& the_marker() const {
return mark;
}
};
sol::state lua;
lua.new_simple_usertype<bark>("bark",
sol::constructors<sol::types<>, sol::types<int>>(),
"fun", sol::protect( &bark::fun ),
"get", &bark::get,
"var", &bark::var,
"the_marker", &bark::the_marker,
"x", sol::property(&bark::get),
"y", sol::property(&bark::set),
"z", sol::property(&bark::get, &bark::set)
);
lua.script("bx = bark.new(760)");
bark& bx = lua["bx"];
REQUIRE(bx.var == 760);
lua.script("b = bark.new()");
bark& b = lua["b"];
lua.script("b:fun()");
int var = b.var;
REQUIRE(var == 51);
lua.script("b:var(20)");
lua.script("v = b:var()");
int v = lua["v"];
REQUIRE(v == 20);
lua.script("m = b:the_marker()");
marker& m = lua["m"];
REQUIRE_FALSE(b.mark.value);
REQUIRE_FALSE(m.value);
m.value = true;
REQUIRE(&b.mark == &m);
REQUIRE(b.mark.value);
sol::table barktable = lua["bark"];
barktable["special"] = &bark::special;
lua.script("s = b:special()");
std::string s = lua["s"];
REQUIRE(s == "woof");
lua.script("b:y(24)");
lua.script("x = b:x()");
int x = lua["x"];
REQUIRE(x == 24);
lua.script("z = b:z(b:z() + 5)");
int z = lua["z"];
REQUIRE(z == 29);
}