So I stole some of Luc Danton's sequence advice to sFuller and Pubby (about sequences), and I generated this "stop messing around with operator," version:
#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 can be out of order (ie, it can ask for arg 2 from Lua before arg 1), but the right one will be passed to the right argument.
Here is a test run: http://ideone.com/XVmQQ6
CheckLuaValuereturn its values? As atuple?...ing parameters: stackoverflow.com/questions/12030538/…