Я использую специальный контейнер для чисел.
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
, чтобы избежать проблем с точностью. Точно так же, как это делается в чистых выражениях C.
Один из способов достижения этого - сначала преобразовать объект VectorFloat
в VectorDouble
а затем выполнить операцию добавления в "двойном мире". Это можно сделать вручную (назначая переменную float во временную двойную) или автоматически компилятором во временную переменную. Насколько мне известно, для этого мне нужно иметь параметрический конструктор или оператор присваивания в 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;
}