Добавить конструктор преобразования в специализацию шаблона

Фон

Я реализую специальный контейнер для чисел.

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> { ... };

0

Решение

Это может быть сделано с 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;
}
3

Другие решения