Addresses derp from refactoring and #12

This commit is contained in:
ThePhD 2016-02-12 12:47:05 -05:00
parent a71c9737d4
commit 228609ee17
14 changed files with 271 additions and 321 deletions

View File

@ -1,4 +1,4 @@
// The MIT License (MIT)
// The MIT License (MIT)
// Copyright (c) 2013-2016 Rapptz and contributors
@ -41,33 +41,32 @@ private:
}
template<std::size_t... I, typename... Ret>
std::tuple<Ret...> invoke( indices<I...>, types<Ret...>, std::ptrdiff_t n ) const {
auto invoke( types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n ) const {
luacall( n, sizeof...( Ret ) );
int nreturns = static_cast<int>( sizeof...( Ret ) );
int stacksize = lua_gettop( lua_state( ) );
int firstreturn = std::max( 0, stacksize - nreturns ) + 1;
auto r = std::make_tuple( stack::get<Ret>( lua_state( ), firstreturn + I )... );
lua_pop( lua_state( ), nreturns );
int firstreturn = std::max(1, stacksize - static_cast<int>(sizeof...(Ret)) + 1);
auto r = stack::get<std::tuple<Ret...>>( lua_state( ), firstreturn );
lua_pop(lua_state(), static_cast<int>(sizeof...(Ret)));
return r;
}
template<std::size_t I, typename Ret>
Ret invoke( indices<I>, types<Ret>, std::ptrdiff_t n ) const {
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n ) const {
luacall( n, 1 );
return stack::pop<Ret>( lua_state( ) );
}
template <std::size_t I>
void invoke( indices<I>, types<void>, std::ptrdiff_t n ) const {
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n) const {
luacall( n, 0 );
}
function_result invoke( indices<>, types<>, std::ptrdiff_t n ) const {
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n ) const {
int stacksize = lua_gettop( lua_state( ) );
int firstreturn = std::max( 1, stacksize - static_cast<int>( n ) );
luacall( n, LUA_MULTRET );
luacall(n, LUA_MULTRET);
int poststacksize = lua_gettop( lua_state( ) );
int returncount = poststacksize - firstreturn;
int returncount = poststacksize - (firstreturn - 1);
return function_result( lua_state( ), firstreturn, returncount, returncount, call_error::ok );
}
@ -87,18 +86,15 @@ public:
}
template<typename... Ret, typename... Args>
auto operator()( types<Ret...>, Args&&... args ) const
-> decltype( invoke( types<Ret...>( ), types<Ret...>( ), 0 ) ) {
decltype(auto) operator()( types<Ret...>, Args&&... args ) const {
return call<Ret...>( std::forward<Args>( args )... );
}
template<typename... Ret, typename... Args>
auto call( Args&&... args ) const
-> decltype( invoke( types<Ret...>( ), types<Ret...>( ), 0 ) ) {
decltype(auto) call( Args&&... args ) const {
push( );
int pushcount = stack::push_args( lua_state( ), std::forward<Args>( args )... );
auto tr = types<Ret...>( );
return invoke( tr, tr, pushcount );
return invoke( types<Ret...>( ), std::index_sequence_for<Ret...>(), pushcount );
}
};
@ -140,28 +136,27 @@ private:
}
template<std::size_t... I, typename... Ret>
std::tuple<Ret...> invoke(indices<I...>, types<Ret...>, std::ptrdiff_t n, handler& h) const {
auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, handler& h) const {
luacall(n, sizeof...(Ret), h);
int nreturns = static_cast<int>(sizeof...(Ret));
int stacksize = lua_gettop(lua_state());
int firstreturn = std::max(0, stacksize - nreturns) + 1;
auto r = std::make_tuple(stack::get<Ret>(lua_state(), firstreturn + I)...);
lua_pop(lua_state(), nreturns);
int firstreturn = std::max(0, stacksize - static_cast<int>(sizeof...(Ret)) + 1);
auto r = stack::get<std::tuple<Ret...>>(lua_state(), firstreturn);
lua_pop(lua_state(), static_cast<int>(sizeof...(Ret)));
return r;
}
template<std::size_t I, typename Ret>
Ret invoke(indices<I>, types<Ret>, std::ptrdiff_t n, handler& h) const {
Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
luacall(n, 1, h);
return stack::pop<Ret>(lua_state());
}
template <std::size_t I>
void invoke(indices<I>, types<void>, std::ptrdiff_t n, handler& h) const {
void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
luacall(n, 0, h);
}
function_result invoke(indices<>, types<>, std::ptrdiff_t n, handler& h) const {
function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
bool handlerpushed = error_handler.valid();
int stacksize = lua_gettop(lua_state());
int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
@ -204,19 +199,16 @@ public:
}
template<typename... Ret, typename... Args>
auto operator()(types<Ret...>, Args&&... args) const
-> decltype(invoke(types<Ret...>(), types<Ret...>(), 0, std::declval<handler&>())) {
decltype(auto) operator()(types<Ret...>, Args&&... args) const {
return call<Ret...>(std::forward<Args>(args)...);
}
template<typename... Ret, typename... Args>
auto call(Args&&... args) const
-> decltype(invoke(types<Ret...>(), types<Ret...>(), 0, std::declval<handler&>())) {
decltype(auto) call(Args&&... args) const {
handler h(error_handler);
push();
int pushcount = stack::push_args(lua_state(), std::forward<Args>(args)...);
auto tr = types<Ret...>();
return invoke( tr, tr, pushcount, h );
return invoke(types<Ret...>(), std::index_sequence_for<Ret...>(), pushcount, h);
}
};
@ -235,8 +227,7 @@ struct pusher<function_sig<Sigs...>> {
template<typename Fx>
static void set_memfx(types<>, lua_State* L, Fx&& fx) {
typedef Unwrapped<Unqualified<Fx>> fx_t;
typedef decltype(&fx_t::operator()) Sig;
set_memfx(types<function_signature_t<Sig>>(), L, std::forward<Fx>(fx));
set(L, &fx_t::operator(), std::forward<Fx>(fx));
}
template<typename... Args, typename R>
@ -251,13 +242,13 @@ struct pusher<function_sig<Sigs...>> {
template<typename... Args, typename R, typename C, typename T>
static void set(lua_State* L, R (C::*memfxptr)(Args...), T&& obj) {
typedef Bool<is_specialization_of<T, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
typedef Bool<is_specialization_of<Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
set_reference_fx(is_reference(), L, memfxptr, std::forward<T>(obj));
}
template<typename Sig, typename C, typename T>
static void set(lua_State* L, Sig C::* memfxptr, T&& obj) {
typedef Bool<is_specialization_of<T, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
typedef Bool<is_specialization_of<Unqualified<T>, std::reference_wrapper>::value || std::is_pointer<T>::value> is_reference;
set_reference_fx(is_reference(), L, memfxptr, std::forward<T>(obj));
}
@ -323,8 +314,8 @@ struct pusher<function_sig<Sigs...>> {
template<typename Fx>
static void set_fx(lua_State* L, std::unique_ptr<base_function> luafunc) {
const auto& metakey = usertype_traits<Unqualified<Fx>>::metatable;
const char* metatablename = std::addressof(metakey[0]);
const static auto& metakey = u8"sol.ƒ.♲.🗑.(/¯◡ ‿ ◡)/¯ ~ ┻━┻ (ノ◕ヮ◕)ノ*:・゚✧";
const static char* metatablename = &metakey[0];
base_function* target = luafunc.release();
void* userdata = reinterpret_cast<void*>(target);
lua_CFunction freefunc = &base_function::call;
@ -352,13 +343,13 @@ struct pusher<function_sig<Sigs...>> {
template<typename T, typename... Args>
struct pusher<sol::detail::function_packer<T, Args...>> {
template <std::size_t... I, typename FP>
static int push_func(indices<I...>, lua_State* L, FP&& fp) {
static int push_func(std::index_sequence<I...>, lua_State* L, FP&& fp) {
return stack::push<T>(L, std::get<I>(fp)...);
}
template <typename FP>
static int push(lua_State* L, FP&& fp) {
return push_func(build_indices<sizeof...(Args)>(), L, std::forward<FP>(fp));
return push_func(std::index_sequence_for<Args...>(), L, std::forward<FP>(fp));
}
};
@ -372,28 +363,28 @@ struct pusher<std::function<Signature>> {
template<typename... Functions>
struct pusher<overload_set<Functions...>> {
template<std::size_t... I, typename Set>
static int push(indices<I...>, lua_State* L, Set&& set) {
static int push(std::index_sequence<I...>, lua_State* L, Set&& set) {
pusher<function_sig<>>{}.set_fx<Set>(L, std::make_unique<overloaded_function<Functions...>>(std::get<I>(set)...));
return 1;
}
template<typename Set>
static int push(lua_State* L, Set&& set) {
return push(build_indices<sizeof...(Functions)>(), L, std::forward<Set>(set));
return push(std::index_sequence_for<Functions...>(), L, std::forward<Set>(set));
}
};
template<typename Signature>
struct getter<std::function<Signature>> {
typedef function_traits<Signature> fx_t;
typedef typename fx_t::args_type args_type;
typedef tuple_types_t<typename fx_t::return_type> return_type;
typedef typename fx_t::args_type args_types;
typedef tuple_types<typename fx_t::return_type> return_types;
template<typename... FxArgs, typename... Ret>
static std::function<Signature> get_std_func(types<FxArgs...>, types<Ret...>, lua_State* L, int index = -1) {
template<typename... Args, typename... Ret>
static std::function<Signature> get_std_func(types<Args...>, types<Ret...>, lua_State* L, int index = -1) {
sol::function f(L, index);
auto fx = [f, L, index](FxArgs&&... args) -> return_type_t<Ret...> {
return f(types<Ret...>(), std::forward<FxArgs>(args)...);
auto fx = [f, L, index](Args&&... args) -> return_type_t<Ret...> {
return f.call<Ret...>(std::forward<Args>(args)...);
};
return std::move(fx);
}
@ -413,7 +404,7 @@ struct getter<std::function<Signature>> {
}
static std::function<Signature> get(lua_State* L, int index) {
return get_std_func(args_type(), return_type(), L, index);
return get_std_func(args_types(), return_types(), L, index);
}
};
} // stack

View File

@ -36,16 +36,6 @@ private:
int popcount;
call_error error;
template <typename T, std::size_t I>
stack::get_return<T> get(types<T>, indices<I>) const {
return stack::get<T>(L, index);
}
template <typename... Ret, std::size_t... I>
stack::get_return<Ret...> get(types<Ret...>, indices<I...>) const {
return stack::get_return<Ret...>(stack::get<Ret>(L, index + I)...);
}
public:
function_result() = default;
function_result(lua_State* L, int index = -1, int returncount = 0, int popcount = 0, call_error error = call_error::ok): L(L), index(index), returncount(returncount), popcount(popcount), error(error) {
@ -85,8 +75,7 @@ public:
template<typename T>
T get() const {
tuple_types<Unqualified<T>> tr;
return get(tr, tr);
return stack::get<T>(L, index);
}
~function_result() {

View File

@ -49,21 +49,21 @@ function_packer<Sig, Args...> function_pack( Args&&... args ) {
return function_packer<Sig, Args...>(std::forward<Args>(args)...);
}
inline bool check_types(types<>, indices<>, lua_State*, int) {
inline bool check_types(types<>, std::index_sequence<>, lua_State*, int) {
return true;
}
template <typename Arg, typename... Args, std::size_t I, std::size_t... In>
inline bool check_types(types<Arg, Args...>, indices<I, In...>, lua_State* L, int start = 1) {
inline bool check_types(types<Arg, Args...>, std::index_sequence<I, In...>, lua_State* L, int start = 1) {
if (!stack::check<Arg>(L, start + I, no_panic))
return false;
return check_types(types<Args...>(), indices<In...>(), L, start);
return check_types(types<Args...>(), std::index_sequence<In...>(), L, start);
}
template<typename T, typename Func, typename = void>
struct functor {
typedef member_traits<Func> traits_type;
typedef callable_traits<Func> traits_type;
typedef typename traits_type::args_type args_type;
typedef typename traits_type::return_type return_type;
@ -97,7 +97,7 @@ struct functor {
template<typename T, typename Func>
struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::value>> {
typedef member_traits<Func> traits_type;
typedef callable_traits<Func> traits_type;
typedef typename traits_type::args_type args_type;
typedef typename traits_type::return_type return_type;
T* item;
@ -129,7 +129,7 @@ struct functor<T, Func, std::enable_if_t<std::is_member_object_pointer<Func>::va
template<typename T, typename Func>
struct functor<T, Func, std::enable_if_t<std::is_function<Func>::value || std::is_class<Func>::value>> {
typedef member_traits<Func> traits_type;
typedef callable_traits<Func> traits_type;
typedef remove_one_type<typename traits_type::args_type> args_type;
typedef typename traits_type::return_type return_type;
typedef std::tuple_element_t<0, typename traits_type::args_tuple_type> Arg0;

View File

@ -36,8 +36,8 @@ struct functor_function : public base_function {
functor_function(Args&&... args): fx(std::forward<Args>(args)...) {}
template<typename... Args>
int operator()(types<void> r, types<Args...> t, lua_State* L) {
stack::call(L, 0, r, t, fx);
int operator()(types<void> tr, types<Args...> ta, lua_State* L) {
stack::call(tr, ta, L, 0,fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
@ -45,7 +45,7 @@ struct functor_function : public base_function {
template<typename... Ret, typename... Args>
int operator()(types<Ret...> tr, types<Args...> ta, lua_State* L) {
return_type r = stack::call(L, 0, tr, ta, fx);
return_type r = stack::call(tr, ta, L, 0, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, r);
@ -64,7 +64,7 @@ template<typename Function, typename T>
struct member_function : public base_function {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_return_t<function_type> return_type;
typedef function_args_t<function_type> args_type;
typedef function_args_t<function_type> args_types;
struct functor {
T member;
function_type invocation;
@ -82,26 +82,12 @@ struct member_function : public base_function {
template<typename Tm, typename... Args>
member_function(Tm&& m, Args&&... args): fx(std::forward<Tm>(m), std::forward<Args>(args)...) {}
template<typename... Args>
int operator()(types<void> tr, types<Args...> ta, lua_State* L) {
stack::call(L, 0, tr, ta, fx);
return 0;
}
template<typename... Ret, typename... Args>
int operator()(types<Ret...> tr, types<Args...> ta, lua_State* L) {
decltype(auto) r = stack::call(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, std::forward<decltype(r)>(r));
}
virtual int operator()(lua_State* L) override {
return (*this)(tuple_types<return_type>(), args_type(), L);
return stack::typed_call(tuple_types<return_type>(), args_types(), fx, L);
}
virtual int operator()(lua_State* L, detail::ref_call_t) override {
return (*this)(tuple_types<return_type>(), args_type(), L);
return (*this)(L);
}
};
} // sol

View File

@ -37,39 +37,40 @@ struct overloaded_function : base_function {
}
int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
int match_arity(std::index_sequence<>, lua_State*, std::ptrdiff_t) {
throw error("no matching function call takes this number of arguments");
}
template <std::size_t I, std::size_t... In>
int match_arity(lua_State* L, std::ptrdiff_t x, indices<I, In...>) {
int match_arity(std::index_sequence<I, In...>, lua_State* L, std::ptrdiff_t x) {
// TODO:
// when we get proper constexpr, search functions only within the specific
// arity range, instead of all of them by using
// std::tuple<
// std::pair<1 - arity, std::tuple<func_arity_of_1_a, func_arity_of_1_b>>,
// std::pair<3 - arity, std::tuple<func_arity_of_3>>,
// std::pair<n - arity, std::tuple<func_arity_of_n, ...>>,
// std::pair<1-arity, std::tuple<func_arity_of_1_a, func_arity_of_1_b>>,
// std::pair<3-arity, std::tuple<func_arity_of_3>>,
// std::pair<n-arity, std::tuple<func_arity_of_n, ...>>,
// ...
//>
auto& package = std::get<I>(overloads);
auto arity = package.first;
if (arity != x) {
return match_arity(L, x, indices<In...>());
return match_arity(std::index_sequence<In...>(), L, x);
}
auto& func = package.second;
typedef Unqualified<decltype(func)> fx_t;
typedef tuple_types<typename function_traits<fx_t>::return_type> return_type;
typedef tuple_types<typename function_traits<fx_t>::return_type> return_types;
typedef typename function_traits<fx_t>::args_type args_type;
if (!detail::check_types(args_type(), args_type(), L)) {
return match_arity(L, x, indices<In...>());
typedef typename args_type::indices args_indices;
if (!detail::check_types(args_type(), args_indices(), L)) {
return match_arity(std::index_sequence<In...>(), L, x);
}
return stack::typed_call<false>(return_type(), args_type(), func, L);
return stack::typed_call<false>(return_types(), args_type(), func, L);
}
int match_arity(lua_State* L) {
std::ptrdiff_t x = lua_gettop(L);
return match_arity(L, x, build_indices<std::tuple_size<overloads_t>::value>());
return match_arity(std::make_index_sequence<std::tuple_size<overloads_t>::value>(), L, x);
}
virtual int operator()(lua_State* L) override {
@ -87,10 +88,10 @@ struct usertype_overloaded_function : base_function {
overloads_t overloads;
usertype_overloaded_function(overload_set<Functions...> set)
: usertype_overloaded_function(build_indices<sizeof...(Functions)>(), set) {}
: usertype_overloaded_function(std::make_index_sequence<sizeof...(Functions)>(), set) {}
template<std::size_t... In>
usertype_overloaded_function(indices<In...>, overload_set<Functions...> set)
usertype_overloaded_function(std::index_sequence<In...>, overload_set<Functions...> set)
: usertype_overloaded_function(std::get<In>(set)...) {}
@ -99,33 +100,34 @@ struct usertype_overloaded_function : base_function {
}
int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
int match_arity(std::index_sequence<>, lua_State*, std::ptrdiff_t) {
throw error("no matching function call takes this number of arguments");
}
template <std::size_t I, std::size_t... In>
int match_arity(lua_State* L, std::ptrdiff_t x, indices<I, In...>) {
int match_arity(std::index_sequence<I, In...>, lua_State* L, std::ptrdiff_t x) {
// TODO:
// propogate changes from above down here too when they get figured out
auto& package = std::get<I>(overloads);
auto arity = package.first;
if (arity != x) {
return match_arity(L, x, indices<In...>());
return match_arity(std::index_sequence<In...>(), L, x);
}
auto& func = package.second;
typedef Unqualified<decltype(func)> fx_t;
typedef tuple_types<typename fx_t::return_type> return_type;
typedef typename fx_t::args_type args_type;
if (!detail::check_types(args_type(), args_type(), L, 2)) {
return match_arity(L, x, indices<In...>());
typedef tuple_types<typename fx_t::return_type> return_types;
typedef typename fx_t::args_type args_type;
typedef typename args_type::indices args_indices;
if (!detail::check_types(args_type(), args_indices(), L, 2)) {
return match_arity(std::index_sequence<In...>(), L, x);
}
func.item = ptr(stack::get<T>(L, 1));
return stack::typed_call<false>(return_type(), args_type(), func, L);
return stack::typed_call<false>(return_types(), args_type(), func, L);
}
int match_arity(lua_State* L) {
std::ptrdiff_t x = lua_gettop(L) - 1;
return match_arity(L, x, build_indices<std::tuple_size<overloads_t>::value>());
return match_arity(std::make_index_sequence<std::tuple_size<overloads_t>::value>(), L, x);
}
virtual int operator()(lua_State* L) override {
@ -145,34 +147,35 @@ struct usertype_indexing_function<overload_set<Functions...>, T> : base_function
std::unordered_map<std::string, std::pair<std::unique_ptr<base_function>, bool>> functions;
usertype_indexing_function(std::string name, overload_set<Functions...> set)
: usertype_indexing_function(build_indices<sizeof...(Functions)>(), std::move(name), set) {}
: usertype_indexing_function(std::index_sequence_for<Functions...>(), std::move(name), set) {}
template <std::size_t... In>
usertype_indexing_function(indices<In...>, std::string name, overload_set<Functions...> set)
usertype_indexing_function(std::index_sequence<In...>, std::string name, overload_set<Functions...> set)
: usertype_indexing_function(std::move(name), std::get<In>(set)...) {}
usertype_indexing_function(std::string name, Functions... fxs)
: overloads({function_traits<Functions>::arity, fxs}...), name(std::move(name)) {}
int match_arity(lua_State*, std::ptrdiff_t, indices<>) {
int match_arity(std::index_sequence<>, lua_State*, std::ptrdiff_t) {
throw error("no matching function call takes this number of arguments");
}
template <std::size_t I, std::size_t... In>
int match_arity(lua_State* L, std::ptrdiff_t x, indices<I, In...>) {
int match_arity(std::index_sequence<I, In...>, lua_State* L, std::ptrdiff_t x ) {
// TODO:
// propogate changes from above down here too when they get figured out
auto& package = std::get<I>(overloads);
auto arity = package.first;
if (arity != x) {
return match_arity(L, x, indices<In...>());
return match_arity(std::index_sequence<In...>(), L, x);
}
auto& func = package.second;
typedef Unqualified<decltype(func)> fx_t;
typedef tuple_types<typename fx_t::return_type> return_type;
typedef typename fx_t::args_type args_type;
if (!detail::check_types(args_type(), args_type(), L, 2)) {
return match_arity(L, x, indices<In...>());
typedef typename args_type::indices args_indices;
if (!detail::check_types(args_type(), args_indices(), L, 2)) {
return match_arity(std::index_sequence<In...>(), L, x);
}
func.item = ptr(stack::get<T>(L, 1));
return stack::typed_call<false>(return_type(), args_type(), func, L);
@ -180,7 +183,7 @@ struct usertype_indexing_function<overload_set<Functions...>, T> : base_function
int match_arity(lua_State* L) {
std::ptrdiff_t x = lua_gettop(L) - 1;
return match_arity(L, x, build_indices<std::tuple_size<overloads_t>::value>());
return match_arity(std::make_index_sequence<std::tuple_size<overloads_t>::value>(), L, x);
}
int prelude(lua_State* L) {

View File

@ -30,27 +30,10 @@ struct static_function {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_traits<function_type> traits_type;
template<typename... Args>
static int typed_call(types<void> tr, types<Args...> ta, function_type* fx, lua_State* L) {
stack::call(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
}
template<typename... Ret, typename... Args>
static int typed_call(types<Ret...>, types<Args...> ta, function_type* fx, lua_State* L) {
typedef return_type_t<Ret...> return_type;
decltype(auto) r = stack::call(L, 0, types<return_type>(), ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, std::forward<decltype(r)>(r));
}
static int call(lua_State* L) {
auto udata = stack::detail::get_as_upvalues<function_type*>(L);
function_type* fx = udata.first;
int r = typed_call(tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L);
int r = stack::typed_call(tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L);
return r;
}
@ -64,31 +47,13 @@ struct static_member_function {
typedef std::remove_pointer_t<std::decay_t<Function>> function_type;
typedef function_traits<function_type> traits_type;
template<typename... Args>
static int typed_call(types<void> tr, types<Args...> ta, T& item, function_type& ifx, lua_State* L) {
auto fx = [&item, &ifx](Args&&... args) -> void { (item.*ifx)(std::forward<Args>(args)...); };
stack::call(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
}
template<typename... Ret, typename... Args>
static int typed_call(types<Ret...> tr, types<Args...> ta, T& item, function_type& ifx, lua_State* L) {
auto fx = [&item, &ifx](Args&&... args) -> return_type_t<Ret...> { return (item.*ifx)(std::forward<Args>(args)...); };
decltype(auto) r = stack::call(L, 0, tr, ta, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, std::forward<decltype(r)>(r));
}
static int call(lua_State* L) {
auto memberdata = stack::detail::get_as_upvalues<function_type>(L, 1);
auto objdata = stack::detail::get_as_upvalues<T*>(L, memberdata.second);
function_type& memfx = memberdata.first;
T& obj = *objdata.first;
int r = typed_call(tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), obj, memfx, L);
return r;
T& item = *objdata.first;
auto fx = [&item, &memfx](auto&&... args) -> typename traits_type::return_type { return (item.*memfx)(std::forward<decltype(args)>(args)...); };
return stack::typed_call(tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), fx, L);
}
int operator()(lua_State* L) {

View File

@ -64,7 +64,7 @@ struct usertype_function_core : public base_function {
template<typename... Args>
int operator()(types<void> tr, types<Args...> ta, lua_State* L) {
//static const std::size_t skew = static_cast<std::size_t>(std::is_member_object_pointer<function_type>::value);
stack::call(L, 0, tr, ta, fx);
stack::call(tr, ta, L, 0, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
@ -72,7 +72,7 @@ struct usertype_function_core : public base_function {
template<typename... Ret, typename... Args>
int operator()(types<Ret...> tr, types<Args...> ta, lua_State* L) {
decltype(auto) r = stack::call(L, 0, tr, ta, fx);
decltype(auto) r = stack::call(tr, ta, L, 0, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
int pushcount = push(L, std::forward<decltype(r)>(r));

View File

@ -33,13 +33,10 @@ public:
object() = default;
template<typename T>
auto as() const -> decltype(stack::get<T>(lua_state())) const {
decltype(auto) as() const {
push();
type actual = stack::get<type>(lua_state());
// This code is actually present
// in almost all of the type-getters,
// and it thus insanely redundant
// type_assert(lua_state(), -1, type_of<T>(), actual);
type_assert(lua_state(), -1, type_of<T>(), actual);
return stack::pop<T>(lua_state());
}
@ -64,7 +61,7 @@ public:
}
template<typename... Ret, typename... Args>
stack::get_return_or<function_result, Ret...> call( Args&&... args ) {
decltype(auto) call( Args&&... args ) {
return this->as<function>()(types<Ret...>(), std::forward<Args>( args )...);
}

View File

@ -35,10 +35,11 @@
namespace sol {
namespace stack {
template<typename T, typename = void>
struct getter;
template<typename T, typename = void>
struct popper;
template<typename T, typename = void>
struct pusher;
template<typename T, type = lua_type_of<T>::value, typename = void>
struct checker;
@ -48,14 +49,6 @@ inline int push(lua_State* L, T&& t, Args&&... args) {
return pusher<Unqualified<T>>{}.push(L, std::forward<T>(t), std::forward<Args>(args)...);
}
template<typename T, std::size_t... I>
inline int push_tuple(lua_State* L, indices<I...>, T&& tuplen) {
using swallow = char[1 + sizeof...(I)];
int pushcount = 0;
swallow {'\0', (pushcount += sol::stack::push(L, std::get<I>(tuplen)), '\0')... };
return pushcount;
}
// overload allows to use a pusher of a specific type, but pass in any kind of args
template<typename T, typename Arg, typename... Args>
inline int push(lua_State* L, Arg&& arg, Args&&... args) {
@ -76,16 +69,13 @@ inline int push_args(lua_State* L, T&& t, Args&&... args) {
}
template<typename T>
inline auto get(lua_State* L, int index = -1) -> decltype(getter<Unqualified<T>>{}.get(L, index)) {
inline decltype(auto) get(lua_State* L, int index = -1) {
return getter<Unqualified<T>>{}.get(L, index);
}
template<typename T>
auto pop(lua_State* L) -> decltype(get<T>(L)) {
typedef decltype(get<T>(L)) ret_t;
ret_t r = get<T>(L);
lua_pop(L, 1);
return r;
inline decltype(auto) pop(lua_State* L) {
return popper<Unqualified<T>>{}.pop(L);
}
template <typename T, typename Handler>
@ -103,12 +93,6 @@ bool check(lua_State* L, int index) {
return check<T>(L, index, handler);
}
template<typename... Ret>
using get_return = ReturnType<decltype(stack::get<Ret>( nullptr, 0 ))...>;
template<typename Empty, typename... Ret>
using get_return_or = ReturnTypeOr<Empty, decltype(stack::get<Ret>( nullptr, 0 ))...>;
namespace detail {
const bool default_check_arguments =
#ifdef SOL_CHECK_ARGUMENTS
@ -150,6 +134,14 @@ struct userdata_pusher<T*> {
}
};
template<typename T, std::size_t... I>
inline int push_tuple(std::index_sequence<I...>, lua_State* L, T&& tuplen) {
using swallow = char[1 + sizeof...(I)];
int pushcount = 0;
swallow {'\0', (pushcount += sol::stack::push(L, std::get<I>(tuplen)), '\0')... };
return pushcount;
}
template <typename T, typename Key, typename... Args>
inline int push_confirmed_userdata(lua_State* L, Key&& metatablekey, Args&&... args) {
userdata_pusher<T>{}.push(L, std::forward<Key>(metatablekey), std::forward<Args>(args)...);
@ -248,31 +240,37 @@ struct checker<T, type::userdata, C> {
template<typename T, typename>
struct getter {
template<typename U = T, EnableIf<std::is_floating_point<U>> = 0>
static U get(lua_State* L, int index = -1) {
return static_cast<U>(lua_tonumber(L, index));
}
static T& get(lua_State* L, int index = -1) {
return getter<T&>{}.get(L, index);
}
};
template<typename U = T, EnableIf<std::is_integral<U>, std::is_signed<U>> = 0>
static U get(lua_State* L, int index = -1) {
template<typename T>
struct getter<T, std::enable_if_t<std::is_floating_point<T>::value>> {
static T get(lua_State* L, int index = -1) {
return static_cast<T>(lua_tonumber(L, index));
}
};
template<typename T>
struct getter<T, std::enable_if_t<And<std::is_integral<T>, std::is_signed<T>>::value>> {
static T get(lua_State* L, int index = -1) {
return static_cast<T>(lua_tointeger(L, index));
}
};
template<typename U = T, EnableIf<std::is_integral<U>, std::is_unsigned<U>> = 0>
static U get(lua_State* L, int index = -1) {
typedef std::make_signed_t<U> signed_int;
return static_cast<U>(stack::get<signed_int>(L, index));
template<typename T>
struct getter<T, std::enable_if_t<And<std::is_integral<T>, std::is_unsigned<T>>::value>> {
static T get(lua_State* L, int index = -1) {
return static_cast<T>(lua_tointeger(L, index));
}
};
template<typename U = T, EnableIf<std::is_base_of<reference, U>> = 0>
static U get(lua_State* L, int index = -1) {
template<typename T>
struct getter<T, std::enable_if_t<std::is_base_of<reference, T>::value>> {
static T get(lua_State* L, int index = -1) {
return T(L, index);
}
template<typename U = T, EnableIf<Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
static U& get(lua_State* L, int index = -1) {
return getter<T&>{}.get(L, index);
}
};
template<typename T>
@ -318,7 +316,7 @@ struct getter<bool> {
template<>
struct getter<std::string> {
static std::string get(lua_State* L, int index = -1) {
std::string::size_type len;
std::size_t len;
auto str = lua_tolstring(L, index, &len);
return { str, len };
}
@ -350,7 +348,7 @@ struct getter<userdata> {
template<>
struct getter<light_userdata> {
static light_userdata get(lua_State* L, int index = 1) {
static light_userdata get(lua_State* L, int index = -1) {
return{ lua_touserdata(L, index) };
}
};
@ -364,32 +362,78 @@ struct getter<upvalue> {
template<>
struct getter<void*> {
static void* get(lua_State* L, int index = 1) {
static void* get(lua_State* L, int index = -1) {
return lua_touserdata(L, index);
}
};
template<typename... Args>
struct getter<std::tuple<Args...>> {
template <std::size_t... I>
static decltype(auto) apply(std::index_sequence<I...>, lua_State* L, int index = -1) {
return std::tuple<decltype(stack::get<Args>(L, index + I))...>(stack::get<Args>(L, index + I)...);
}
static decltype(auto) get(lua_State* L, int index = -1) {
return apply(std::index_sequence_for<Args...>(), L, index);
}
};
template <typename T, typename>
struct popper {
inline decltype(auto) pop(lua_State* L) {
decltype(auto) r = get<T>(L);
lua_pop(L, 1);
return r;
}
};
template <typename... Args>
struct popper<std::tuple<Args...>> {
inline decltype(auto) pop(lua_State* L) {
decltype(auto) r = get<std::tuple<Args...>>(L, lua_gettop(L) - sizeof...(Args));
lua_pop(L, sizeof...(Args));
return r;
}
};
template<typename T, typename>
struct pusher {
template<typename U = T, EnableIf<std::is_floating_point<U>> = 0>
static int push(lua_State* L, T& t) {
return detail::push_userdata<T>(L, usertype_traits<T>::metatable, t);
}
static int push(lua_State* L, T&& t) {
return detail::push_userdata<T>(L, usertype_traits<T>::metatable, std::move(t));
}
};
template<typename T>
struct pusher<T, std::enable_if_t<std::is_floating_point<T>::value>> {
static int push(lua_State* L, const T& value) {
lua_pushnumber(L, value);
return 1;
}
}
};
template<typename U = T, EnableIf<std::is_integral<U>, std::is_signed<U>> = 0>
template<typename T>
struct pusher<T, std::enable_if_t<And<std::is_integral<T>, std::is_signed<T>>::value>> {
static int push(lua_State* L, const T& value) {
lua_pushinteger(L, value);
return 1;
}
};
template<typename U = T, EnableIf<std::is_integral<U>, std::is_unsigned<U>> = 0>
template<typename T>
struct pusher<T, std::enable_if_t<And<std::is_integral<T>, std::is_unsigned<T>>::value>> {
static int push(lua_State* L, const T& value) {
typedef std::make_signed_t<T> signed_int;
return stack::push(L, static_cast<signed_int>(value));
}
};
template<typename U = T, EnableIf<has_begin_end<U>, Not<has_key_value_pair<U>>> = 0>
template<typename T>
struct pusher<T, std::enable_if_t<And<has_begin_end<T>, Not<has_key_value_pair<T>>>::value>> {
static int push(lua_State* L, const T& cont) {
lua_createtable(L, static_cast<int>(cont.size()), 0);
unsigned index = 1;
@ -403,8 +447,10 @@ struct pusher {
}
return 1;
}
};
template<typename U = T, EnableIf<has_begin_end<U>, has_key_value_pair<U>> = 0>
template<typename T>
struct pusher<T, std::enable_if_t<And<has_begin_end<T>, has_key_value_pair<T>>::value>> {
static int push(lua_State* L, const T& cont) {
lua_createtable(L, static_cast<int>(cont.size()), 0);
for(auto&& pair : cont) {
@ -414,21 +460,13 @@ struct pusher {
}
return 1;
}
};
template<typename U = T, EnableIf<std::is_base_of<reference, U>> = 0>
template<typename T>
struct pusher<T, std::enable_if_t<std::is_base_of<reference, T>::value>> {
static int push(lua_State*, T& ref) {
return ref.push();
}
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
static int push(lua_State* L, T& t) {
return detail::push_userdata<U>(L, usertype_traits<T>::metatable, t);
}
template<typename U = Unqualified<T>, EnableIf<Not<has_begin_end<U>>, Not<std::is_base_of<reference, U>>, Not<std::is_integral<U>>, Not<std::is_floating_point<U>>> = 0>
static int push(lua_State* L, T&& t) {
return detail::push_userdata<U>(L, usertype_traits<T>::metatable, std::move(t));
}
};
template<typename T>
@ -479,8 +517,8 @@ struct pusher<void*> {
template<>
struct pusher<upvalue> {
static int push(lua_State* L, upvalue upvalue) {
lua_pushlightuserdata(L, upvalue);
static int push(lua_State* L, upvalue upv) {
lua_pushlightuserdata(L, upv);
return 1;
}
};
@ -495,10 +533,9 @@ struct pusher<light_userdata> {
template<>
struct pusher<userdata> {
template<typename T, typename U = Unqualified<T>>
static int push(lua_State* L, T&& data) {
U* userdata = static_cast<U*>(lua_newuserdata(L, sizeof(U)));
new(userdata)U(std::forward<T>(data));
static int push(lua_State* L, userdata data) {
void** ud = static_cast<void**>(lua_newuserdata(L, sizeof(void*)));
*ud = data.value;
return 1;
}
};
@ -531,7 +568,7 @@ template<typename... Args>
struct pusher<std::tuple<Args...>> {
template <typename Tuple>
static int push(lua_State* L, Tuple&& tuplen) {
return push_tuple(L, build_indices<sizeof...(Args)>(), std::forward<Tuple>(tuplen));
return detail::push_tuple(std::index_sequence_for<Args...>(), L, std::forward<Tuple>(tuplen));
}
};
@ -568,7 +605,7 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
template <bool b>
struct check_arguments {
template <std::size_t I0, std::size_t... I, typename Arg0, typename... Args>
static bool check(lua_State* L, int firstargument, indices<I0, I...>, types<Arg0, Args...>) {
static bool check(types<Arg0, Args...>, std::index_sequence<I0, I...>, lua_State* L, int firstargument) {
bool checks = true;
stack::check<Arg0>(L, firstargument + I0);
using swallow = int[sizeof...(Args)+2];
@ -578,7 +615,7 @@ struct check_arguments {
return checks;
}
static bool check(lua_State*, int, indices<>, types<>) {
static bool check(types<>, std::index_sequence<>, lua_State*, int) {
return true;
}
};
@ -586,27 +623,27 @@ struct check_arguments {
template <>
struct check_arguments<false> {
template <std::size_t... I, typename... Args>
static bool check(lua_State*, int, indices<I...>, types<Args...>) {
static bool check(types<Args...>, std::index_sequence<I...>, lua_State*, int) {
return true;
}
};
template <bool checkargs = detail::default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(lua_State* L, int start, indices<I...>, types<R>, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
inline R call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
const int stacksize = lua_gettop(L);
const int firstargument = static_cast<int>(start + stacksize - std::max(sizeof...(Args)-1, static_cast<std::size_t>(0)));
detail::check_arguments<checkargs>{}.check(L, firstargument, ta, ta);
detail::check_arguments<checkargs>{}.check(ta, tai, L, firstargument);
return fx(std::forward<FxArgs>(args)..., stack::get<Args>(L, firstargument + I)...);
}
template <bool checkargs = detail::default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs>
inline void call(lua_State* L, int start, indices<I...>, types<void>, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
const int stacksize = lua_gettop(L);
const int firstargument = static_cast<int>(start + stacksize - std::max(sizeof...(Args)-1, static_cast<std::size_t>(0)));
bool checks = detail::check_arguments<checkargs>{}.check(L, firstargument, ta, ta);
bool checks = detail::check_arguments<checkargs>{}.check(ta, tai, L, firstargument);
if ( !checks )
throw error("Arguments not of the proper types for this function call");
@ -636,44 +673,46 @@ inline void remove( lua_State* L, int index, int count ) {
}
}
template <bool checkargs = detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(lua_State* L, int start, types<R> tr, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
return detail::call<checkargs>(L, start, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
template <bool check_args = detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(types<R> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
typedef typename types<Args...>::indices args_indices;
return detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
template <bool checkargs = detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(lua_State* L, types<R> tr, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
return call<checkargs>(L, 0, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
template <bool check_args = detail::default_check_arguments, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(types<R> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
return call<check_args>(tr, ta, L, 0, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
template <bool checkargs = detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
inline void call(lua_State* L, int start, types<void> tr, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
detail::call<checkargs>(L, start, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
template <bool check_args = detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
inline void call(types<void> tr, types<Args...> ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
typedef typename types<Args...>::indices args_indices;
detail::call<check_args>(tr, ta, args_indices(), L, start, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
template <bool checkargs = detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
inline void call(lua_State* L, types<void> tr, types<Args...> ta, Fx&& fx, FxArgs&&... args) {
call<checkargs>(L, 0, ta, tr, ta, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
template <bool check_args = detail::default_check_arguments, typename... Args, typename Fx, typename... FxArgs>
inline void call(types<void> tr, types<Args...> ta, lua_State* L, Fx&& fx, FxArgs&&... args) {
call<check_args>(tr, ta, L, 0, std::forward<Fx>(fx), std::forward<FxArgs>(args)...);
}
template<bool check_args = detail::default_check_arguments, typename... Args, typename Fx>
inline int typed_call(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
stack::call<check_args>(L, 0, tr, ta, fx);
inline int typed_call(types<void> tr, types<Args...> ta, Fx&& fx, lua_State* L, int start = 0) {
call<check_args>(tr, ta, L, start, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return 0;
}
template<bool check_args = detail::default_check_arguments, typename... Ret, typename... Args, typename Fx>
inline int typed_call(types<Ret...> tr, types<Args...> ta, Fx&& fx, lua_State* L) {
decltype(auto) r = stack::call<check_args>(L, 0, tr, ta, fx);
inline int typed_call(types<Ret...>, types<Args...> ta, Fx&& fx, lua_State* L, int start = 0) {
decltype(auto) r = call<check_args>(types<ReturnType<Ret...>>(), ta, L, start, fx);
int nargs = static_cast<int>(sizeof...(Args));
lua_pop(L, nargs);
return stack::push(L, std::forward<decltype(r)>(r));
return push(L, std::forward<decltype(r)>(r));
}
inline call_syntax get_call_syntax(lua_State* L, const std::string& meta) {
if (sol::stack::get<type>(L, 1) == type::table) {
if (get<type>(L, 1) == type::table) {
if (luaL_newmetatable(L, meta.c_str()) == 0) {
lua_settop(L, -2);
return call_syntax::colon;

View File

@ -82,17 +82,18 @@ class table_core : public reference {
}
template<typename Keys, typename... Ret, std::size_t... I>
stack::get_return<Ret...> tuple_get( types<Ret...>, indices<I...>, Keys&& keys ) const {
return stack::get_return<Ret...>( single_get<Ret>( std::get<I>( keys ) )... );
std::tuple<decltype(stack::get<Ret>(nullptr, 0))...> tuple_get( types<Ret...>, std::index_sequence<I...>, Keys&& keys ) const {
typedef std::tuple<decltype(single_get<Ret>(0))...> tup;
return tup( single_get<Ret>( std::get<I>( keys ) )... );
}
template<typename Keys, typename Ret, std::size_t I>
decltype(auto) tuple_get( types<Ret>, indices<I>, Keys&& keys ) const {
decltype(auto) tuple_get( types<Ret>, std::index_sequence<I>, Keys&& keys ) const {
return single_get<Ret>( std::get<I>( keys ) );
}
template<typename Pairs, std::size_t... I>
void tuple_set( indices<I...>, Pairs&& pairs ) {
void tuple_set( std::index_sequence<I...>, Pairs&& pairs ) {
using swallow = int[];
swallow{ 0, ( single_set(std::get<I * 2>(pairs), std::get<I * 2 + 1>(pairs)) , 0)..., 0 };
}
@ -111,12 +112,12 @@ public:
template<typename... Ret, typename... Keys>
decltype(auto) get( Keys&&... keys ) const {
return tuple_get( types<Ret...>( ), build_indices<sizeof...( Ret )>( ), std::forward_as_tuple(std::forward<Keys>(keys)...));
return tuple_get( types<Ret...>( ), std::index_sequence_for<Ret...>( ), std::forward_as_tuple(std::forward<Keys>(keys)...));
}
template<typename... Args>
table_core& set( Args&&... args ) {
tuple_set(build_indices<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
tuple_set(std::make_index_sequence<sizeof...(Args) / 2>(), std::forward_as_tuple(std::forward<Args>(args)...));
return *this;
}

View File

@ -135,7 +135,7 @@ template <typename... Args>
using return_type_t = typename return_type<Args...>::type;
template <typename Empty, typename... Args>
using ReturnTypeOr = typename std::conditional<(sizeof...(Args) < 1), Empty, typename return_type<Args...>::type>::type;
using ReturnTypeOr = typename std::conditional<(sizeof...(Args) < 1), Empty, return_type_t<Args...>>::type;
template <typename... Args>
using ReturnType = ReturnTypeOr<void, Args...>;
@ -178,9 +178,6 @@ struct check_deducible_signature {
template<class F>
struct has_deducible_signature : detail::check_deducible_signature<F>::type { };
template<typename T>
using has_deducible_signature_t = typename has_deducible_signature<T>::type;
template<typename T>
struct Function : Bool<detail::is_function_impl<T>::value> {};
@ -256,7 +253,7 @@ struct fx_traits<R(*)(Args...), false> {
} // detail
template<typename Signature>
struct function_traits : detail::fx_traits<Signature> {};
struct function_traits : detail::fx_traits<std::remove_volatile_t<Signature>> {};
template<typename Signature>
using function_args_t = typename function_traits<Signature>::args_type;
@ -269,12 +266,12 @@ using function_return_t = typename function_traits<Signature>::return_type;
namespace detail {
template<typename Signature, bool b = std::is_member_object_pointer<Signature>::value>
struct member_traits : function_traits<Signature> {
struct callable_traits : function_traits<Signature> {
};
template<typename Signature>
struct member_traits<Signature, true> {
struct callable_traits<Signature, true> {
typedef typename remove_member_pointer<Signature>::type Arg;
typedef typename remove_member_pointer<Signature>::type R;
typedef Signature signature_type;
@ -292,7 +289,7 @@ struct member_traits<Signature, true> {
} // detail
template<typename Signature>
struct member_traits : detail::member_traits<Signature> {
struct callable_traits : detail::callable_traits<std::remove_volatile_t<Signature>> {
};

View File

@ -26,49 +26,10 @@
#include <cstddef>
namespace sol {
template<typename... Ts>
struct reverse_tuple;
template<typename... Ts>
using reverse_tuple_t = typename reverse_tuple<Ts...>::type;
template<>
struct reverse_tuple<std::tuple<>> {
using type = std::tuple<>;
};
template<typename T, typename... Ts>
struct reverse_tuple<std::tuple<T, Ts...>> {
using head = std::tuple<T>;
using tail = typename reverse_tuple<std::tuple<Ts...>>::type;
using type = decltype(std::tuple_cat(std::declval<tail>(), std::declval<head>()));
};
template<size_t... Ns>
struct indices { typedef indices type; };
template<size_t N, size_t... Ns>
struct build_indices : build_indices<N - 1, N - 1, Ns...> {};
template<size_t... Ns>
struct build_indices<0, Ns...> : indices<Ns...> {};
template<size_t N, size_t... Ns>
struct build_reverse_indices : build_reverse_indices<N - 1, Ns..., N - 1> {};
template<size_t... Ns>
struct build_reverse_indices<0, Ns...> : indices<Ns...> {};
template<typename... Args>
struct types : build_indices<sizeof...(Args)> { typedef types type; static constexpr std::size_t size() { return sizeof...(Args); } };
struct types { typedef std::index_sequence_for<Args...> indices; static constexpr std::size_t size() { return sizeof...(Args); } };
namespace detail {
template<class Acc, class... Args>
struct reversed_ : Acc{};
template<typename... RArgs, typename Arg, typename... Args>
struct reversed_<types<RArgs...>, Arg, Args...> : reversed_<types<Arg, RArgs...>, Args...>{};
template<typename Arg>
struct chop_one : types<> {};
@ -77,19 +38,17 @@ struct chop_one<types<Arg0, Arg1, Args...>> : types<Arg1, Args...> {};
template<typename Arg, typename... Args>
struct chop_one<types<Arg, Args...>> : types<Args...> {};
template<typename... Args>
struct tuple_types_ { typedef types<Args...> type; };
template<typename... Args>
struct tuple_types_<std::tuple<Args...>> { typedef types<Args...> type; };
} // detail
template<typename... Args>
struct reversed : detail::reversed_<types<>, Args...>{};
template<typename... Args>
struct tuple_types : types<Args...> {};
template<typename... Args>
struct tuple_types<std::tuple<Args...>> : types<Args...> {};
template<typename... Args>
using tuple_types_t = typename tuple_types<Args...>::type;
using tuple_types = typename detail::tuple_types_<Args...>::type;
template<typename Arg>
struct remove_one_type : detail::chop_one<Arg> {};

View File

@ -97,7 +97,7 @@ private:
template<typename... Args>
static void do_constructor(lua_State* L, T* obj, call_syntax syntax, int, types<Args...>) {
default_construct fx{};
stack::call(L, -1 + static_cast<int>(syntax), types<void>(), types<Args...>(), fx, obj);
stack::call(types<void>(), types<Args...>(), L, -1 + static_cast<int>(syntax), fx, obj);
}
static void match_constructor(lua_State*, T*, call_syntax, int) {

View File

@ -396,6 +396,30 @@ TEST_CASE("advanced/call_lambdas", "A C++ lambda is exposed to lua and called")
REQUIRE(x == 9);
}
TEST_CASE("advanced/call_referenced_obj", "A C++ object is passed by pointer/reference_wrapper to lua and invoked") {
sol::state lua;
int x = 0;
auto objx = [&](int new_x) {
x = new_x;
return 0;
};
lua.set_function("set_x", std::ref(objx));
int y = 0;
auto objy = [&](int new_y) {
y = new_y;
return std::tuple<int, int>(0, 0);
};
lua.set_function("set_y", &decltype(objy)::operator(), std::ref(objy));
lua.script("set_x(9)");
lua.script("set_y(9)");
REQUIRE(x == 9);
REQUIRE(y == 9);
}
TEST_CASE("negative/basic_errors", "Check if error handling works correctly") {
sol::state lua;
@ -465,7 +489,7 @@ TEST_CASE("tables/functions_variables", "Check if tables and function calls work
REQUIRE_NOTHROW(run_script(lua));
}
TEST_CASE("functions/overloaded", "Check if overloaded function resolution templates compile/work") {
TEST_CASE("functions/overload-resolution", "Check if overloaded function resolution templates compile/work") {
sol::state lua;
lua.open_libraries(sol::lib::base);
@ -1149,8 +1173,7 @@ TEST_CASE("functions/destructor-tests", "Show that proper copies / destruction h
REQUIRE(last_call == static_call);
}
REQUIRE(created == 1);
REQUIRE(destroyed == 1);
REQUIRE(created == destroyed);
REQUIRE(destroyed == 2);
}
}