Я реализую специальный контейнер для чисел.
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...
}
Затем он используется для различных типов, особенно для двойного и плавающего:
typedef VectorBase<float> VectorFloat;
typedef VectorBase<double> VectorDouble;
Теперь я хотел бы использовать такую конструкцию
VectorFloat inFloat;
VectorDouble inDouble;
VectorDouble outDouble = inFloat + inDouble;
Где я хочу гарантировать, что операция сложения выполняется на double
объекты, а не на float
чтобы избежать проблем с точностью. Точно так же, как это делается в чистых выражениях Си.
Один из способов достижения этого — сначала преобразовать VectorFloat
возражать в VectorDouble
а затем выполните операцию сложения в «двойном мире». Это может быть сделано вручную (присваивая переменной с плавающей точкой временную двойную переменную) или автоматически компилятором во временную переменную. Насколько мне известно, для этого мне нужно иметь параметрический конструктор или оператор присваивания на VectorDouble
который принимает аргумент типа VectorFloat
и делает фактическое преобразование.
Можно ли добавить новый параметрический конструктор в специализацию шаблона без необходимости репликации всего кода шаблона для определенного параметра шаблона?
VectorBase<double>::VectorBase<double>(const VectorBase<float> &b) { ... }
Я знаю, что могу создать производный класс, который будет содержать необходимый параметрический конструктор, но это не сработает для меня, поскольку мне нужно извлечь другой класс из VectorBase
позже, сохранив шаблон:
template<typename T>
class VerySpecialDerivedVector: public VectorBase<T> { ... };
Это может быть сделано с 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;
}