2015-11-06 4 views
2

Учитывая следующий векторный класс (предназначенный для 2d, 3d или 4d векторной математики), который использует std :: array, можно ли определить конструктор вариаций и/или конструктор преобразования?Преобразователь/конструктор, определенный пользователем Variadic

В качестве последующего вопроса, это такая плохая практика? Мне нужно, чтобы конвертировать в-целое число, float и double довольно много.

Я знаю, что неявные преобразования произойдут, но мой компилятор даст мне предупреждения об этом (я не хочу их вообще отключать).

#include <array> 

template<typename T0, size_t S> 
class Vec 
{ 
public: 

    static_assert(S > 1 && S < 5, "vector dimension must be between 2 and 4"); 
    static_assert(std::is_arithmetic<T0>::value, "type must be arithmetic"); 

    std::array<T0, S> v; 

    Vec() = default; 

    template<class T1, class T2> 
    Vec(T1 t1, T2 t2) : v({ static_cast<T0>(t1), 
          static_cast<T0>(t2) }) {} 

    template<class T1, class T2, class T3> 
    Vec(T1 t1, T2 t2, T3 t3) : v({ static_cast<T0>(t1), 
            static_cast<T0>(t2), 
            static_cast<T0>(t3) }) {} 

    template<class T1, class T2, class T3, class T4> 
    Vec(T1 t1, T2 t2, T3 t3, T4 t4) : v({ static_cast<T0>(t1), 
              static_cast<T0>(t2), 
              static_cast<T0>(t3), 
              static_cast<T0>(t4) }) {} 
}; 

int main(void) 
{ 
    auto foo1 = Vec<float, 2>(1, 2); 
    auto foo2 = Vec<float, 2>(1.0f, 2.0f); 
    auto foo3 = Vec<float, 2>(1.0, 2.0); 
    auto foo4 = Vec<float, 2>(1u, 2u); 

    return 0; 
} 
+1

Вашего статическое утверждение относительно параметра шаблона S кажется странным. Если он должен быть больше 1 и меньше 3, вы могли бы просто сказать, что это должно быть 2. – antred

+0

Спасибо. Починил это. 2, 3 или 4. – Robinson

ответ

2

Конечно, это возможно.

Кстати, в таком случае вам не нужен конструктор по умолчанию, так как это VARIADIC конструктор еще лучше таким образом, что он будет обнулить ваш массив ...

template<typename T0, size_t S> 
class Vec 
{ 
public: 

    static_assert(S > 1 && S < 3, "vector dimension must be between 2 and 4"); 
    static_assert(std::is_arithmetic<T0>::value, "type must be arithmetic"); 

    std::array<T0, S> v; 

    template <typename ...T> 
    Vec(T&& ...a) : v{{ static_cast<T0>(std::forward<T>(a))...}} 
    {} 
}; 
+0

О, это умно. Спасибо. Я думаю, мне нужно обновление: «ошибка C2797:« Vec :: v »: инициализация списка внутри списка инициализаторов членов или инициализатор нестатических данных не реализован» – Robinson

+0

Примечание для любого пользователя с VS 2013, это компилирует «Vec (T1 && ... a): v ({static_cast (a) ...}) {} " – Robinson

1

Из вашего примера, он смотрит на меня что представленные значения имеют одинаковый тип в любом случае. Итак, почему бы вам не использовать std::initializer_list? Кроме того, вы передали их типу T0, прежде чем передавать их во внутреннее std::array, так что, возможно, это того стоит. На самом деле вам не нужны типы аргументов, насколько вы можете их отнести к T0.

+0

Они обычно имеют один и тот же тип, но иногда они этого не делают. – Robinson

+0

Получил. Не было видно из примера. Во всяком случае, это факт, что вас действительно не интересуют их типы. Вы не можете воспользоваться этим? Все ответы, которые вы получаете, используют этот факт, не так ли? – skypjack

+0

Это не самая важная вещь, если честно. – Robinson

2

Если добавить последовательность индексов к шаблону класса:

template<typename T0, size_t S, typename = std::make_index_sequence<S>> 
class Vec; 

Вы можете использовать эту дополнительную вещь, чтобы определить, как конструктор:

template<typename T0, size_t S, size_t... Idx> 
class Vec<T0, S, std::index_sequence<Idx...>> 
{ 
    template <size_t> using ith_T = T0; 

    ... 

    Vec(ith_T<Idx>... ts) 
    : v({ts...}) // no cast necessary, they're already T0 
    { } 

    template <typename U, 
       typename = std::enable_if_t<std::is_convertible<U, T0>::value> 
       > 
    Vec(const Vec<U, S>& rhs) 
    : v({static_cast<T0>(rhs.v[Idx])...}) 
    { } 

    ... 
}; 
Смежные вопросы