我正在编写一个通用函数包装器,它可以将任何函数包装到具有该形式的lua样式调用中
int lua_function(lua_State * L)
我希望包装函数是即时生成的,所以我想将函数作为模板参数传递 . 如果你知道参数的数量(例如2),这是微不足道的:
template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
但是,我不知道这个数字,所以我请求variadic模板参数求助
// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
上面的内容不会编译,因为variadic参数必须是最后一个 . 所以我使用两个级别的模板,外部模板捕获类型,内部模板捕获函数:
template <typename R, typename... Args>
struct func_type<R(Args...)>
{
// Inner function wrapper take the function pointer as a template argument
template <R F(Args...)>
struct func
{
static int call( lua_State *L )
{
// extract arguments from L
F(/*arguments*/);
return 1;
}
};
};
这是有效的,除了包装像这样的函数
double sin(double d) {}
用户必须写
func_type<decltype(sin)>::func<sin>::apply
这很乏味 . 问题是:有没有更好的,用户友好的方式来做到这一点? (我不能用函数模板来包装整个东西,因为函数参数不能用作模板参数 . )
2 回答
像
std::function
和std::result_of
之类的东西使用以下技术来做你想要的变量模板:你可以扩展上面的内容来添加一个非类型
Ret(&P)(Args...)
模板参数(指向函数的指针也是如此),但你仍然需要在用户级别decltype
,即wrapper<decltype(sin), sin>::apply
. 可以说,如果您决定使用宏来删除重复,那么它将是预处理器的合法使用 .以上编译与ideone的gcc-4.5 . 运行应用程序(可变地)弹出参数,祝你好运(如果你打开一个关于那个的问题,请给我留言) . 你考虑过使用Luabind吗?
正如@Juraj在他的评论中所说,函数指针可以是模板参数,请参阅以下简单示例:
工作版:http://www.ideone.com/LP0TO
我正常使用
BOOST_TYPEOF
,因为我总是在当前标准中提供示例,但它的作用类似于decltype
. 这是你追求的吗?