So, I stole some of the Luc Danton sequence recommendations for sFuller and Pubby (about sequences), and I created this version of "stop messing around with operator, ":
#include <iostream> struct lua_State {}; template<typename T> T CheckLuaValue( int n, lua_State* l) { std::cout << "arg[" << n << "] gotten\n"; return T(n); } template<int ...> struct seq { }; // generates a seq< First, ..., Last-1 > as "type" template<int First, int Last> struct gen_seq { template<int N, int... S> struct helper : helper<N-1, N-1, S...> {}; template<int... S> struct helper<First, S...> { typedef seq<S...> type; }; typedef typename helper<Last>::type type; }; template< typename X > struct MemberFunctionWrapper; template< typename F > struct MemberFunctionHelper { typedef F MethodPtr; }; template<class InstanceType, typename ReturnType, typename... Params> struct MemberFunctionWrapper< ReturnType(InstanceType::*)(Params...) > { typedef MemberFunctionHelper<ReturnType(InstanceType::*)(Params...)> Helper; typedef typename Helper::MethodPtr MethodPtr; static MethodPtr& GetFunctionPointer() {static MethodPtr pFunc; return pFunc;} static InstanceType*& GetMemberPointer() {static InstanceType* pThis;return pThis;} template<int n, typename Param> static auto GetLuaValue( lua_State* luaState )->decltype(CheckLuaValue<Param>(n,luaState)) { return CheckLuaValue<Param>(n,luaState); } template< typename sequence > struct call; template< int... I > struct call<seq<I...>> { ReturnType operator()( lua_State* luaState, InstanceType* instance, MethodPtr method ) const { return (instance->*method)( GetLuaValue<I,Params>( luaState )... ); } }; static int CFunctionWrapper( lua_State* luaState) { MethodPtr func = GetFunctionPointer(); InstanceType* instance = GetMemberPointer(); ReturnType retval = call< typename gen_seq< 1, sizeof...(Params)+1 >::type >()( luaState, instance, func ); return 0; } }; struct test{ int foo(int x, double d){std::cout << "x:" << x << " d:" << d << "\n";}}; int main(){ typedef MemberFunctionWrapper< int(test::*)(int, double) > wrapper; test bar; wrapper::GetFunctionPointer() = &test::foo; wrapper::GetMemberPointer() = &bar; wrapper::CFunctionWrapper(0); }
now note that the calls to CheckLuaValue may be out of order (i.e. it may request arg 2 from Lua before arg 1), but the right one will be passed into the correct argument.
Here is a test run: http://ideone.com/XVmQQ6
Yakk - Adam Nevraumont Nov 19 2018-12-12T00: 00Z
source share