【发布时间】:2013-03-26 22:33:40
【问题描述】:
我希望创建一个可以多态地在浮点数组和双精度数组之间转换的类。也就是说,相关实例(由<double> 或<float> 参数化)以及传递float* 或double* 的决定是在运行时决定的,而不是静态决定的。
作为proposed answer 到另一个问题,但根据this answer 修改(因为我知道不可能在类中完全专门化成员函数模板),提供简单重载的纯虚拟基类BaseDest成员函数被子类化以定义DestImpl<T>。我使用这个基类来维护DestImpl<T> 实例的动态集合,其中有不同的T。此类提供assign() 成员函数的显式重载;一个用于double *,另一个用于float *。这个想法是,在运行时,BaseDest::assign() 通过多态指针或引用被调用,这反过来又在DestImpl<T> 中调用正确的虚拟assign() 成员函数。
现在,重要的是数组的非指针类型匹配 DestImpl<T> 中的 T,调用 fast_copy() 函数(可能是 memcpy),并且当类型不匹配时,静态速度较慢 -执行逐项复制。所以assign() 成员函数将其卸载到模板化的functor。这个函子有两种特化——一种是函子的类型参数与 DestImpl<T> 的类型匹配(因此调用快速复制),另一种是捕获所有其他情况的回退(并调用慢速复制) .
但是,我无法编译以下代码。 cmets 显示编译器错误和警告出现的位置 - 我怀疑它们是相关的。我不明白的是为什么apply_helper 的第二个特化无法实例化为apply_helper<double>。
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
void assign(const double * v, size_t cnt) {
assign_helper<T>()(v, cnt);
}
void assign(const float * v, size_t cnt) {
assign_helper<T>()(v, cnt); // ERROR: no matching function for call to object of type 'assign_helper<double>'
}
protected:
template <typename U>
struct assign_helper {
void operator()(const U * v, size_t cnt) {
for (size_t i = 0; i < cnt; ++i) {
//slow_copy(v[i]);
}
}
};
template <typename U>
struct assign_helper<T> { // WARNING: Class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used
void operator()(const T * v, size_t cnt) {
//fast_copy(v, cnt);
}
};
};
void test() {
DestImpl<double> d; // error mentioned above appears when this is present
}
编辑:这似乎确实有效 - 将 assign_helper 结构(现在是一个类)从 DestImpl<T> 类定义中移出。我不确定这是不是正确的方法,但到目前为止它似乎确实有效:
// slow copy between different types
template <typename T, typename U>
class assign_helper {
public:
void operator()(const U *v, size_t cnt) {
// slow copy
}
};
// fast copy between same types
template <typename T>
class assign_helper<T, T> {
public:
void operator()(const T * v, size_t cnt) {
// fast copy
}
};
class BaseDest {
public:
virtual ~BaseDest() {}
virtual void assign(const double * v, size_t cnt) = 0;
virtual void assign(const float * v, size_t cnt) = 0;
};
template <typename T>
class DestImpl : public BaseDest {
public:
virtual void assign(const double * v, size_t cnt) {
assign_helper<T, double>()(v, cnt);
}
virtual void assign(const float * v, size_t cnt) {
assign_helper<T, float>()(v, cnt);
}
};
【问题讨论】:
标签: c++ templates type-conversion template-specialization