函数作为模板参数,以及可变参数模板参数
functions as template argument, plus variadic template argument
我正在编写一个通用的函数包装器,它可以将任何函数包装成lua风格的调用,其形式为:
int lua_function( lua_State *L)
我希望包装函数是即时生成的,所以我正在考虑将该函数作为模板参数传递。如果您知道参数的数量(例如,2),这是微不足道的:
template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
但是,我不知道数字,所以我乞求可变参数模板参数寻求帮助
// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
上面的内容不会编译,因为可变参数必须是最后一个。所以我使用两级模板,外部模板捕获类型,内部模板捕获函数:
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
这很乏味。问题是:有没有更好、更用户友好的方法呢?(我不能使用函数模板来包装整个事情,因为函数参数不能用作模板参数。
像 std::function
和 std::result_of
之类的东西使用以下技术来执行您想要的可变参数模板:
template<typename Signature>
struct wrapper; // no base template
template<typename Ret, typename... Args>
struct wrapper<Ret(Args...)> {
// instantiated for any function type
};
您可以扩展上述内容以添加非类型Ret(&P)(Args...)
模板参数(指向函数的指针也可以正常工作),但您仍然需要在用户级别进行decltype
,即 wrapper<decltype(sin), sin>::apply
.可以说,如果您决定使用宏来删除重复,这将是对预处理器的合法使用。
template<typename Sig, Sig& S>
struct wrapper;
template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
int
static apply(lua_State*)
{
// pop arguments
// Ret result = P(args...);
// push result & return
return 1;
}
};
// &wrapper<decltype(sin), sin>::apply is your Lua-style wrapper function.
以上编译与 gcc-4.5 在 ideone 上。祝你好运,实现(可变地)弹出参数的应用程序(如果您对此提出问题,请给我发表评论)。您是否考虑过使用 Luabind?
正如@Juraj在他的评论中所说,函数指针可以是模板参数,请参阅以下简单示例:
#include <iostream>
#include <boost/typeof/typeof.hpp>
void f(int b, double c, std::string const& g)
{
std::cout << "f(): " << g << std::endl;
}
template <typename F, F* addr>
struct wrapper
{
void operator()()
{
std::string bar("bar");
(*addr)(1, 10., bar);
}
};
int main(void)
{
wrapper<BOOST_TYPEOF(f), &f> w;
w();
return 0;
}
工作版本: http://www.ideone.com/LP0TO
我像往常一样使用BOOST_TYPEOF
我总是在当前标准中提供示例,但它的作用类似于 decltype
.这就是你所追求的吗?
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)