我正在为lua
. 它通过实例化函数模板来工作,该模板将 a 提供的参数收集lua
到 astd::tuple
中,然后将std::tuple
a 应用于指向成员函数的指针。这是一个例子:
template <member_meta_info const* mmi, class C, class R, class ...A>
inline typename std::enable_if<std::is_same<void, R>::value, int>::type
member_stub(lua_State* L)
{
assert(sizeof...(A) + 1 == lua_gettop(L));
static std::tuple<A...> args;
set_args<0, 2>(args, L);
lua_getfield(L, -1, "__instance");
assert(lua_islightuserdata(L, -1));
typedef R (C::*ptr_to_member_type)(A...);
apply_tuple(static_cast<C*>(lua_touserdata(L, -1)),
*static_cast<ptr_to_member_type*>(mmi->ptr_to_member), args);
lua_pushnil(L);
return 1;
}
mmi->ptr_to_member
只是一个void*
指针。诀窍是从以下set_args
方面偷来的:
迭代元组:
template<std::size_t I = 0, std::size_t O = 1, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp)>::type
set_args(std::tuple<Tp...>&, lua_State*)
{
}
template<std::size_t I = 0, std::size_t O = 1, typename... Tp>
inline typename std::enable_if<I != sizeof...(Tp)>::type
set_args(std::tuple<Tp...>& t, lua_State* L)
{
set_arg(L, I + O, std::get<I>(t));
set_args<I + 1, O, Tp...>(t, I);
}
set_arg()
是一组用于设置引用的各种原始类型(例如int
, double
, ...)的重载函数,从 中返回std::get<>
,例如:
inline void set_arg(lua_State* L, std::size_t i, double& value)
{
assert(lua_isnumber(L, i));
value = lua_tonumber(L, i);
}
该apply
技巧改编自:
如何将元组扩展为可变参数模板函数的参数?
#ifndef APPLYTUPLE_HPP
# define APPLYTUPLE_HPP
template<size_t N>
struct Apply {
template<typename F, typename T, typename... A>
static inline auto apply(F&& f, T && t, A &&... a)
-> decltype(Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
))
{
return Apply<N-1>::apply(::std::forward<F>(f), ::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
);
}
template<typename C, typename F, typename T, typename... A>
static inline auto apply(C && c, F && f, T && t, A &&... a)
-> decltype(Apply<N-1>::apply(::std::forward<C>(c),
::std::forward<F>(f), ::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
))
{
return Apply<N-1>::apply(::std::forward<C>(c), ::std::forward<F>(f),
::std::forward<T>(t), ::std::get<N-1>(::std::forward<T>(t)),
::std::forward<A>(a)...
);
}
template<typename C, typename T, typename... A>
static inline C* apply(T && t, A &&... a)
{
return Apply<N-1>::template apply<C>(::std::forward<T>(t),
::std::get<N-1>(::std::forward<T>(t)), ::std::forward<A>(a)...
);
}
};
template<>
struct Apply<0> {
template<typename F, typename T, typename... A>
static inline auto apply(F && f, T &&, A &&... a)
->decltype((*::std::forward<F>(f))(::std::forward<A>(a)...))
{
return (*::std::forward<F>(f))(::std::forward<A>(a)...);
}
template<typename C, typename F, typename T, typename... A>
static inline auto apply(C && c, F && f, T &&, A &&... a)
->decltype((::std::forward<C>(c)->*::std::forward<F>(f))(::std::forward<A>(a)...))
{
return (::std::forward<C>(c)->*::std::forward<F>(f))(::std::forward<A>(a)...);
}
template<typename C, typename T, typename... A>
static inline C* apply(T &&, A &&... a)
{
return new C(::std::forward<A>(a)...);
}
};
template<typename F, typename T>
inline auto apply_tuple(F && f, T && t)
->decltype(Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t)))
{
return Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<F>(f), ::std::forward<T>(t));
}
template<typename C, typename F, typename T>
inline auto apply_tuple(C && c, F && f, T && t)
->decltype(Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<C>(c), ::std::forward<F>(f), ::std::forward<T>(t)))
{
return Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::apply(::std::forward<C>(c), ::std::forward<F>(f), ::std::forward<T>(t));
}
template<typename C, typename T>
inline C* apply_tuple(T && t)
{
return Apply< ::std::tuple_size<
typename ::std::decay<T>::type
>::value>::template apply<C>(::std::forward<T>(t));
}
#endif // APPLYTUPLE_HPP
它将元组应用于args
指向的成员函数。现在我的问题。我很不安,对于每个函数调用,我都将lua
提供的所有参数复制到 a 中std::tuple
,然后将其应用到指向成员的指针上。当然,复制需要一些开销。是否可以以某种方式省略复制?是否存在比现有容器更适合复制参数的容器(标准或其他)std::tuple
(即脂肪较少,修剪较多)。