我正在为数字实现一个专用容器。
template <typename T>
class VectorBase
{
// Some constructors...
friend VectorBase<T> operator+(const VectorBase& a, const VectorBase& b)
{
VectorBase<T> res;
// Addition...
return res;
}
// Additional non-trivial logic...
}
然后用于各种类型,尤其是double和float:
typedef VectorBase<float> VectorFloat;
typedef VectorBase<double> VectorDouble;
现在我想使用像这样的构造
VectorFloat inFloat;
VectorDouble inDouble;
VectorDouble outDouble = inFloat + inDouble;
我希望保证在double
个对象上执行添加操作,而不是float
个对象,以避免精度问题。正如在纯C表达式中所做的那样。
实现此目的的一种方法是首先将VectorFloat
对象转换为VectorDouble
,然后在“双世界”中执行加法运算。这可以手动完成(将float变量分配给临时双精度变量)或由编译器自动完成。据我所知,要做到这一点,我需要在VectorDouble
上有一个参数化构造函数或赋值运算符,它接受VectorFloat
类型的参数并进行实际转换。
是否可以将新的参数构造函数添加到模板的特化中,而无需复制特定模板参数的整个模板代码?
VectorBase<double>::VectorBase<double>(const VectorBase<float> &b) { ... }
我知道我可以创建一个派生类,它将包含所需的参数构造函数,但这对我不起作用,因为我需要稍后从VectorBase
派生另一个类,同时仍然保持模板:
template<typename T>
class VerySpecialDerivedVector: public VectorBase<T> { ... };
答案 0 :(得分:3)
可以使用SFINAE完成,例如:
template <typename T2,
typename = typename std::enable_if<std::is_same<double, T>::value
&& std::is_same<float, T2>::value>::type>
VectorBase(const VectorBase<T2> &) { /* .. */ }
但我认为最好有:
template <typename T1, typenale T2>
friend VectorBase<typename std::common_type<T1, T2>::type>
operator+(const VectorBase<T1>& a, const VectorBase<T2>& b)
{
using T = typename std::common_type<T1, T2>::type;
VectorBase<T> res;
// Addition...
return res;
}