【发布时间】:2020-03-30 16:47:36
【问题描述】:
我的情况
我有两个类,由不受我控制的外部库提供,例如他们的界面对我来说是固定的。
第一个是模板化的二维容器类型,它允许我操作通过成员函数以及原始指针保存的内容。 第二个是一个包含一堆静态成员函数的类,这些函数抽象了一些经过 SIMD 优化的向量操作。它们中的大多数都被重载以采用不同的数据类型,但是它们都共享相同的接口,例如
VecOperations::op (Type* dest, const Type* src, /* a variable number of operation specific arguments */, int len)
我想要达到的目标:
我想迭代我的 2D 容器的第一个维度,并在第二次迭代中对每个向量应用向量操作。因此我想替换例如
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < container.getXDim(); ++i)
VecOperations::foo (ptrs[i], ptrs[i], arg1, arg2, arg3, container.getYDim());
最好是这样的(伪代码)
forAllElements<VecOperations::foo> (container, arg1, arg2, arg3);
这应该适用于存储在我的容器中的所有类型的类型,这些类型受向量操作类的支持,也适用于所有数量的向量操作特定参数。据我所知,写上面forAllElements 之类的东西是不可能的。
我目前的解决方案:
我想出了这个:
template <typename ElemType, typename ...Args>
struct ForAllElemements
{
template <void(*op)(ElemType*, const ElemType*, Args..., int)>
static void call (Container<ElemType>& buffer, Args... args)
{
auto xDim = container.getXDim();
auto yDim = container.getYDim();
auto** ptrs = conatiner.getArrayOfRawPointers();
for (int i = 0; i < xDim; ++i)
op (ptrs[i], const_cast<const ElemType*>(ptrs[i]), args..., yDim);
}
};
这可以像这样使用
// using a Container<float> and VecOperations::foo (float*, const float*, float, int, float, int)
ForAllElemements<float, float, int, float>::call<VecOperations::foo> (container, arg1, arg2, arg3);
虽然在 C++17 中从构造函数中推导出类模板参数是可行的,但据我所知,从静态函数调用中推导出它是行不通的。据我了解,这根本没有定义,从技术上讲,我看不出有任何原因
ForAllElemements::call<VecOperations::foo> (container, arg1, arg2, arg3);
应该是不可能的,因为所有模板类型都可以从传递给静态函数的参数中推断出来。
所以我问你,是否有任何我不知道的超级聪明的解决方法或模式可以使 C++17 或更高版本的标准成为可能?
【问题讨论】: