2015-11-06 53 views
2

給定以下矢量類(用於2d,3d或4d矢量數學),它使用std :: array,是否可以定義可變參數和/或轉換構造函數?可變的用戶定義的轉換/構造函數

作爲後續的問題,這種事情是不好的做法?我發現自己需要轉換爲整數,浮點數和雙精度。

我知道隱式轉換會發生,但我的編譯器會給我警告(我不想一般關閉它們)。

#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

當然這是可能的。

順便說一句,在這種情況下你不需要的默認構造函數,因爲這個可變參數的構造函數是更好的方式,將零您的陣列...

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])...}) 
    { } 

    ... 
}; 
相關問題