2

I need a way to pass a variable amount of parameters to a function in this circumstance:

template<typename ...T> struct Lunch { Lunch(T...){} }; template<typename T> T CheckLuaValue(lua_State* luaState,int index) { //Do Stuff return value; } template <class MemberType, typename ReturnType, typename... Params> struct MemberFunctionWrapper <ReturnType (MemberType::*) (Params...)> { static int CFunctionWrapper (lua_State* luaState) { ReturnType (MemberType::*)(Params...) functionPointer = GetFunctionPointer(); MemberType* member = GetMemberPointer(); int index = 1; //Get a value for each type in Params Lunch<Params...> { (CheckLuaValue<Params>(luaState,index), index++, void(), 0)... }; 

CheckLuaValue returns a value for each type in Params. My problem is that I now need a way to call my function with all of those values

 member->*functionPointer(returnedLuaValues); } }; 

How would I go about doing this?

3
  • 1
    How does CheckLuaValue return its values? As a tuple? Commented Nov 19, 2012 at 3:08
  • CheckLuaValue returns a single value Commented Nov 19, 2012 at 3:48
  • Ah. Is that the comma operator I see? Anyhow, this stack overflow might be useful, it has a whole bunch of stuff on ...ing parameters: stackoverflow.com/questions/12030538/… Commented Nov 19, 2012 at 4:23

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

Comments

1

If I understand correctly, you should change the definition Lunch to invoke the member function pointer:

template <class MemberType, typename ReturnType, typename... Params> struct MemberFunctionWrapper <ReturnType (MemberType::*) (Params...)> { template<typename ...T> struct foo // new Lunch { foo(ReturnType (MemberType::*)(Params...) functionPointer, MemberType* member, T... args){ member->*functionPointer(args...); } }; static int CFunctionWrapper (lua_State* luaState) { ReturnType (MemberType::*)(Params...) functionPointer = GetFunctionPointer(); MemberType* member = GetMemberPointer(); int index = 1; //member->*(bindedMemberFunction->memberFunction); //Get a value for each type in Params foo<Params...> { functionPointer, member, (++index, CheckLuaValue<Params>(luaState,index))... }; } }; 

12 Comments

shouldn't MemberType member in the constructor be MemberType* member ?
@sFuller Yeah, I didn't compile it so there might be a few syntax errors.
Parameter arguments are not guaranteed to execute in order. How are you guaranteeing that index++ is evaluated in the right order here? Ie, the compiler could evaluate argument 7, then argument 0, then argument 3. I'm guessing that some of those commas are the comma operator? -- which makes me wonder how it is supposed to work (as foo<...> is called with a bunch of 0s?), plus I suspect you might want to comment the use of the comma operator when you use it in the middle of calling a function. :)
@Yakk Comma operator has a sequence point and using brace enclosed initializer syntax enforces left-to-right ordering. sFuller seems to know this. The , 0 is to work around void functions, although this is clearly incorrect here.
@sFuller Syntax when using ptmf's should always be (a.*b)(c, ..., z) or (a->*b)(c, ..., z).
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.