有没有一种方法可以使模板匹配所有指针类型
Is there a way to make a template match all pointer types?
有没有一种方法可以使模板化C++函数隐式地将所有指针转换为void*
?我正在研究一个轻量级的Lua绑定,当我只需要void*
版本时,我希望避免为每个指针类型编写完全相同的函数。
声明:
template<class T>
T GetFromStack(lua_State* L, int index);
定义:
template<> void* GetFromStack<void*>(lua_State* L, int index)
{
return lua_touserdata(L, index);
}
如果我调用myVariable = GetFromStack<MyStruct*>(L, 0);
,C++编译器会抱怨我没有为MyStruct*
定义函数。是否可以将每个指针类型隐式匹配到void*
版本?
编辑:
我发现我的问题有点令人困惑,我真的不知道该怎么说。我正试图想出一个自动绑定系统。这个GetFromStack
函数是从另一个模板化函数调用的:
template<class T_return, class T_param1, class T_param2 >
int LuaFunction(lua_State* L, T_return (*func)(T_param1,T_param2));
它是这样实现的:
template<class T_return, class T_param1, class T_param2 >
int LuaFunction(lua_State* L, T_return (*func)(T_param1,T_param2))
{
T_param1 a = GetFromStack<T_param1>(L, 1);
T_param2 b = GetFromStack<T_param2>(L, 2);
T_return ret = func(a,b);
PushLuaType(L, ret); // <-- This is another templated function
// like GetFromStack that has the same problem
return 1;
}
然后,我用一个简单的宏创建一个Lua版本的任何函数,我想向Lua公开:
#define DeclareLuaFunction(function)
static int ##function##_lua_(lua_State* L)
{
return LuaFunction(L, function);
}
只要我使用预定义的类型,这就非常有效。我有为所有"基本"类型(int、float等)编写的GetFromStack
版本,显然还有void*
。但我不想为我的自定义类型的每一个指针都写一个。当我创建一个使用MyStruct2
的函数时,我必须编写与其他pointer
版本相同的GetFromStack
的另一个版本。
这个系统的使用方式如下:
struct MyStruct
{
int a;
float b;
};
int AddToMyStruct(MyStruct* s, int x)
{
int original = s->a;
s->a += x;
return original;
}
DeclareLuaFunction(AddToMyStruct);
然后将T_return
作为int
,T_param1
作为MyStruct*
,T_param2
也作为整数。我已经有GetFromStack
和PushLuaType
的int
版本,但我没有MyStruct*
版本。按照现在的实现方式,我必须为我提出的每种类型编写一个新版本的GetFromStack
,即使每个实现都是一样的。
编辑:如果有一种方法可以确定一个类型是指针还是不在编译类型,Andreas的解决方案就会奏效。如果我的T_param1是MyStruct*
,那么它将按原样传递给GetFromStack
,而不是MyStruct
。
如果我理解正确,您需要为不同的类型实现不同的函数,但所有指针类型的实现恰好相同。
如果该值是作为参数传递的,那么您将使用普通函数重载。在这种情况下,可以使用enable_if
。
template<typename T>
typename std::enable_if<std::is_pointer<T>::value, T>::type
GetFromStack(lua_State* L, int index)
{
return lua_touserdata(L, index);
}
好的,这是一个基于您的附加信息的新尝试。正如前面所说的,如果您选择使用C++11,那么大部分操作都可以更容易地完成,但这也应该适用于大多数较旧的编译器。
首先,你需要一种方法来检测你的模板参数T是否是一个指针,你可以使用std::is_pointer<>
(这是最好的),也可以自己定义一个:
template <class T>
struct is_pointer
{
enum {value = false};
};
template <class T>
struct is_pointer<T *>
{
enum {value = true};
};
template <class T>
struct is_pointer<const T *>
{
enum {value = true};
};
接下来你需要基于它来改变你的实现。为此,我们引入了一个助手类(或者结构,因为我懒得写public
),它有几个专业化,每个普通类型一个,指针一个:
template <bool ispointer, class T>
struct GetFromStackHelper;
template <>
struct GetFromStackHelper<false, int>
{
static int GetFromStackFun(lua_State *l, int index)
{
return lua_tointeger(l, index);
}
};
// ... add the rest of the built in types here
template <class T>
struct GetFromStackHelper<true, T>
{
static T GetFromStackFun(lua_State *l, int index)
{
return static_cast<T>(lua_touserdata(l, index));
}
};
最后,我们将它与GetFromStack
函数联系在一起,该函数现在不应该有任何专门化:
template <class T>
T GetFromStack(lua_State *l, int index)
{
return GetFromStackHelper<is_pointer<T>::value, T>::GetFromStackFun(l, index);
}
您可以将其用作:
int i = GetFromStack<int>(luaState, 6);
MyStruct *p = GetFromStack<MyStruct *>(luaState, 5);
我不太确定这是否是您想要的,但是。。。
传递函数指针怎么样?
你的编译器可能会给你一堆警告,但它应该可以工作。
void *GetFromStack(void *p, int index, void * (*func)(void *, int)) {
return func(p, index);
}
void * (*func)(void *, int)
是一个函数指针,指向一个接受void指针和int并返回void指针的函数,该指针作为GetFromStack的前两个参数提供。只需使用引用运算符&
来获取要调用的函数的函数指针。
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 如何访问在 c++ 中在类内声明的结构类型指针变量?
- (C )找到基本类型指针的儿童类型
- 表达式必须具有指向对象的指针类型(指针向量)
- 将子项复制构造到父类型指针中
- C 返回类型指针声明
- 调用虚拟函数而不通过类类型指针创建任何对象
- C++ 如何使用类类型指针制作向量
- 为什么基类型指针不能获取派生类对象的地址值?
- 如何在 C++ 中获取映射类型指针,映射
- 如何检查该类型的类型指针是正确对齐的
- 正在转换为短类型指针
- 指向任意类方法的模板非类型指针
- 如何通过强制转换类型指针将字符数组转换为uint16_t
- 指向shared_ptr的不透明类型 C 指针
- C++:从值类型指针强制转换为包含迭代器
- C/C++:访问给定类型指针的位置与访问另一类型指针的相同位置不同
- 比较类型指针
- 数据类型指针使用*(Datatype *)
- 如何打印c++中char类型指针的所有值