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

0

Задний план

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

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> { ... };
Теги:
templates
constructor
template-specialization
arithmetic-expressions

1 ответ

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;
}
  • 0
    Что это за колдовство? Я постараюсь понять это, а затем я попробую это. Спасибо!
  • 0
    @ivokabel: SFINAE для первого. type_traits для второго.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню