【发布时间】:2013-05-16 15:49:09
【问题描述】:
我在使用模板参数创建静态包装函数时遇到了一些问题。我不想将函数直接传递给包装函数,因为它需要特定的签名int (lua_State *),以便可以传递给以下函数:
lua_pushcfunction(L, function);
(没错,我要的是自动生成的 lua 包装器。)
我的第一个想法是创建一个模板函数,将函数指针作为非类型模板参数。
template <void(* f)(void)>
int luaCaller(lua_State * _luaState)
{
f();
return 0;
}
到目前为止,这看起来很不错。此函数具有正确的签名,并调用我通过模板参数传入的函数。
&(luaCaller<myFunc>)
当我尝试将它包装在另一个函数中时,我的问题就出现了。非类型模板参数必须外部链接,因此以下失败:
void pushFunction(lua_State * _luaState, void(* _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
这是有道理的,因为函数的地址需要在编译时知道。您不能只输入任何指针并期望编译器知道要创建哪些类。不幸的是,如果我添加一个 在编译时已知的函数指针,它仍然会失败。函数指针的值被复制到 _a 中,因此 _a 在编译时在技术上仍然未知。因此,我希望以下工作:
void pushFunction(lua_State * _luaState, void(* const _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
或许
void pushFunction(lua_State * _luaState, void(* & _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
在第一种情况下,因为不允许更改值,所以我们知道如果它是外部链接的,它在技术上仍然是外部链接的。在第二种情况下,它作为参考传递,这意味着它应该具有相同的链接,不是吗?但这些尝试都没有奏效。为什么?是否有可能以某种方式规避这一点?如何干净地自动生成调用另一个函数的函数?
【问题讨论】:
-
遗憾的是,仅仅因为参数是
const并且您提供了编译时间常数,不会使参数成为编译时间常数。跨度> -
这对我来说很奇怪。是因为您可以简单地转换为 const 吗?就是这么想的。
-
是的,这是因为当编译器编译
doCaller时,它不知道将来会传递给它什么。其他地方可以并且可能确实传递运行时变量。绝对没有迹象表明编译器该参数是编译时间常数,只有迹象表明一旦函数开始您将不会修改参数。 -
啊,这就是我的意思。有没有办法指定某些东西是编译时间常数?我现在可以看到,出于同样的原因,按引用传递也不起作用。
-
doCaller(_luaState, a)比luaCaller<_a>(_luaState)有什么优势?只需使用第二个。
标签: c++ templates function-pointers