2015-11-06 52 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])...}) 
    { } 

    ... 
}; 
相关问题