C++ 在模板演绎中保留函数指针参数的完整类型
我试图找到一种方法,在传递到模板函数时,保持函数指针参数的完整类型 这是我想做的一个例子:C++ 在模板演绎中保留函数指针参数的完整类型,c++,arrays,templates,c++11,C++,Arrays,Templates,C++11,我试图找到一种方法,在传递到模板函数时,保持函数指针参数的完整类型 这是我想做的一个例子: #include <stdio.h> #include <utility> template<typename _Ret, typename... Args> static _Ret call(_Ret (*fp)(Args&&...), Args &&... args) { return fp(std::forward<
#include <stdio.h>
#include <utility>
template<typename _Ret, typename... Args>
static _Ret call(_Ret (*fp)(Args&&...), Args &&... args)
{
return fp(std::forward<Args>(args)...);
}
int foo(int arr[4])
{
printf("arr: %i,%i,%i,%i\n", arr[0], arr[1], arr[2], arr[3]);
return 0;
}
int main(int, char**)
{
int arr[4] = { 1, 2, 3, 4 };
int (*foo_ptr)(int arr[4]) = &foo;
call<int>(foo_ptr, arr);
return 0;
}
Luaglue函数恰好是这样的:
template<typename _Ret, typename... _Args>
class LuaGlueFunction : public LuaGlueFunctionBase
{
public:
typedef _Ret ReturnType;
typedef _Ret (*MethodType)( _Args... );
LuaGlueFunction(LuaGlueBase *lg, const std::string &n, MethodType fn) :
g(lg), name_(n), fn_(std::forward<decltype(fn)>(fn))
{ }
~LuaGlueFunction() {}
std::string name() { return name_; }
bool glue(LuaGlueBase *luaGlue)
{
lua_pushlightuserdata(luaGlue->state(), this);
lua_pushcclosure(luaGlue->state(), &lua_call_func, 1);
//printf("add function: %s\n", name_.c_str());
lua_setglobal(luaGlue->state(), name_.c_str());
return true;
}
int invoke(lua_State *state)
{
ReturnType ret = applyTuple(g, state, fn_, args);
lua_pop(state, Arg_Count_);
stack<_Ret>::put(g, state, ret);
return 1;
}
private:
LuaGlueBase *g;
std::string name_;
MethodType fn_;
std::tuple<_Args...> args;
static const unsigned int Arg_Count_ = sizeof...(_Args);
static int lua_call_func(lua_State *state)
{
auto mimp = (LuaGlueFunction<_Ret, _Args...> *)lua_touserdata(state, lua_upvalueindex(1));
return mimp->invoke(state);
}
};
模板
类LuaGlueFunction:公共LuaGlueFunctionBase
{
公众:
类型定义返回类型;
typedef _Ret(*MethodType)(_Args…);
LuaGlueFunction(LuaGlueBase*lg,const std::string&n,MethodType fn):
g(lg)、名称(n)、fn(标准::转发(fn))
{ }
~LuaGlueFunction(){}
std::string name(){返回名称}
布尔胶(LuaGlueBase*luaGlue)
{
lua_pushlightuserdata(luaGlue->state(),this);
lua_pushcclosure(luaGlue->state(),&lua_call_func,1);
//printf(“添加函数:%s\n”,name_u.c_str());
lua_setglobal(luaGlue->state(),name_u.c_str());
返回true;
}
int调用(lua_状态*状态)
{
ReturnType ret=applyTuple(g,state,fn_u1;,args);
lua_pop(状态、参数计数);
堆栈::put(g,state,ret);
返回1;
}
私人:
LuaGlueBase*g;
std::字符串名称;
方法fn型;
std::元组参数;
静态常量unsigned int Arg\u Count\u=sizeof…(\u Args);
静态整数lua\u调用函数(lua\u状态*状态)
{
自动mimp=(LuaGlueFunction*)lua_-toserdata(状态,lua_-upvalueindex(1));
返回mimp->invoke(状态);
}
};
我试图允许检测数组,然后在内部将其自动装箱到LuaGlueStaticArray类型中(假设我可以防止数组退化为指针,则该部分已经起作用)
希望这有助于更好地解释我要做的事情。调用函数模板有问题。它需要被定义为
template<typename _Ret, typename... Args>
static _Ret call(_Ret (*fp)(Args...), Args &&... args)
// ^^^ no &&
记住这一点,当您将arr
传递给call
时,您不希望将其推断为int(&)[4]
,因此必须传递一个指针
call<int>(foo_ptr, &arr[0]); // pass a pointer to the beginning
然后称之为
decltype(foo)* foo_ptr = &foo;
call<int>(foo_ptr, arr);
或
调用函数模板时出现问题。它需要被定义为
template<typename _Ret, typename... Args>
static _Ret call(_Ret (*fp)(Args...), Args &&... args)
// ^^^ no &&
记住这一点,当您将arr
传递给call
时,您不希望将其推断为int(&)[4]
,因此必须传递一个指针
call<int>(foo_ptr, &arr[0]); // pass a pointer to the beginning
然后称之为
decltype(foo)* foo_ptr = &foo;
call<int>(foo_ptr, arr);
或
int(*)(int*)
和int(*)(int[4])
是同一类型的两种拼写int(*)(int(&)[4])
是不同的类型,但模板不会凭空生成它,您需要传入该类型的实体。事实上,您是正确的。int(*)(int*)
和int(*)(int[4])
是同一类型的两种拼写int(*)(int(&)[4])
是一种不同的类型,但模板不会凭空生成它,您需要传入该类型的实体。事实上,您是正确的。请注意,如果foo
的类型是int(int(&)[4])
则可以简单地将其称为call(foo,arr)代码>@mpark是的,这就是我在我发布的。或者你的意思是不需要foo_ptr
?如果是这样,我同意,我这么做只是因为OP在问题中这么做了。不需要foo_ptr
yes,但也需要显式模板参数:call
@mpark啊,是的,这值得一提。我已经更新了答案。谢谢。将call
的实际参数类型与fp
的形式参数分开推导,可以进行隐式转换,这样call(foo,&arr[0])
和call(foo,arr)
都是有效的()。请注意,如果foo
的类型是int(int(&)[4])
然后您可以简单地将其称为call(foo,arr)代码>@mpark是的,这就是我在我发布的。或者你的意思是不需要foo_ptr
?如果是这样,我同意,我这么做只是因为OP在问题中这么做了。不需要foo_ptr
yes,但也需要显式模板参数:call
@mpark啊,是的,这值得一提。我已经更新了答案。谢谢。将call
的实际参数类型与fp
的形式参数分开推导,可以进行隐式转换,这样call(foo,&arr[0])
和call(foo,arr)
都是有效的()。
call(foo, &arr[0]); // with int foo(int *arr)
call(foo, arr); // with int foo(int (&arr)[4])