请原谅任何语法错误。我的C ++代码设置类似于:
template<typename T>
void addytox(T *x, T *y, int n)
{
for(int i = 0; i < n; ++i) {
x[i] += y[i];
}
return;
}
void my_func(void *x, void *y, int n, int dtype)
{
/* Here is where I am unsure of how to do a simple static cast using
the dtype identifier. I want to avoid long code using a switch or
if/else that would check all possible conditions, for example having
code that looks like this:
if (dtype == 0) {
addytox((int*)x, (int*)y, n);
}
else if (dtype == 1) {
addytox((float*)x, (float*)y, n);
}
else if (dtype == 2) {
addytox((double*)x, (double*)y, n);
}
else {
//Print/log some error...
exit;
}
return;
*/
}
它设置的代码是这样的原因是因为my_func指向可以是任何类型的NumPy数组(int,float32,float64等),而我通过ctypes从Python调用my_func。我知道C ++不会知道NumPy数组是什么类型,但我可以轻松地在Python中获取数据类型,并将其传递给my_func(在本例中为整数dtype)。我想知道的是,如果我可以使用该标识符,只能使用正确的类型转换来调用函数addytox一次。
例如:
addytox((cast_type*)x, (cast_type*)y, n));
是否有可能在C ++中做这样的事情,如果是这样,我该如何去做呢?
谢谢。
答案 0 :(得分:2)
不幸的是,我理解这个问题,使用模板编译时间类型确定不会在运行时帮助您。你几乎坚持使用switch-type机制来确定你需要在运行时调用的类型。
但是,我可以分享一些出色的模板元编程技术。这些有助于缩小编译和运行时类型确定之间的差距。
// Generic Declaration. Note the default value.
// For any of the TypeId's not specialized, the compiler will give errors.
template<int TypeId = 0>
struct DispatchAddYToX;
// Specialize for typeId = 0, which let's say is int
template<>
struct DispatchAddYToX<0> // Let's say TypeId 0 = int
{
enum { MyId = 0 };
typedef int MyType;
void dispatch(void* x, void* y, int n, int dType)
{
// Expanded version, for clarity.
if(dType == MyId)
{
// Awriiite! We have the correct type ID.
// ADL should take care of lookup.
addYToX((MyType*)x, (MyType*)y, n);
}
else
{
// If not the correct ID for int, try the next one.
DispatchAddYToX<MyId + 1>::dispatch(x, y, n, dType);
}
}
};
// Specialize for typeId = 1, which let's say is float
template<>
struct DispatchAddYToX<1> // Let's say TypeId 1 = float
{
enum { MyId = 1 };
typedef float MyType;
void dispatch(void* x, void* y, int n, int dType)
{
// Nice and compact version
(dType == MyId) ? addYToX((MyType*)x, (MyType*)y, n) :
DispatchAddYToX<MyId + 1>::dispatch(x, y, n, dType);
}
};
...
// And so on for the rest of the type id's.
// Now for a C-style wrapper.
// Use this with your python hook
void addYToXWrapper(void* x, void*y, int n, int dType)
{
// Defaults to start at 0 (int)
// Will replace the switch statement.
DispatchAddYToX::dispatch(x, y, n, dType);
}
所以最后,它是一个奇特的切换表,几乎完全相同。在我看来,界面更清洁:)