I have the following code:
lib.hxx:
template <typename C, typename R, typename ... Args>
R Lib::extract_call(lua_State* L, R(C::*method)(Args...))
{
return static_cast<C*>(this)->*method(extract_data<Args>(L)...);
}
lib.cc:
template <>
std::string Lib::extract_data(lua_State* L)
{
if (! lua_isstring(L, -1))
{
return "";
}
return lua_tostring(L, -1);
}
[...] // Other specializations following
I am embedding lua in a project, and I'm currently looking for a way to call methods from lua, and from a dispatcher extract arguments automatically from the lua stack. From those "simple" templates it is possible to easily generate the calls needed to extract data from the lua stack given in parameter without any typing error.
BUT, my problem is, when extract_data<Args>(L)...
is unpacked, the order of evaluation for all extract_data
calls are unspecified (as stated in standard, for optimization purposes), while it really matters in which order you extract data from the lua stack.
On the other hand, I can't regroup all of these calls in an initializer list since they are of different type.
Therefore, how can I ensure extract_data
calls to be in a specific order, or at least keep an automated way to pass arguments to my member pointer function ?
EDIT: I had forgotten that the calls need to be in revert order, which I don't think is achievable by any language mechanism. Therefore, here is my solution, back to regular, non variadic templates:
template <typename C, typename R, typename A1>
R Lib::extract_call(lua_State* L, R(C::*method)(A1))
{
return (static_cast<C*>(this)->*method)(extract_data<A1>(L));
}
template <typename C, typename R, typename A1, typename A2>
R Lib::extract_call(lua_State* L, R(C::*method)(A1, A2))
{
A2 b = extract_data<A2>(L);
A1 a = extract_data<A1>(L);
return (static_cast<C*>(this))->*method(a,b);
}
template <typename C, typename R,
typename A1, typename A2, typename A3>
R Lib::extract_call(lua_State* L, R(C::*method)(A1, A2, A3))
{
A3 c = extract_data<A3>(L);
A2 b = extract_data<A2>(L);
A1 a = extract_data<A1>(L);
return (static_cast<C*>(this))->*method(a,b,c);
}
// And so on up to 8 arguments