变量用户定义的转换/构造函数

时间:2015-11-06 20:17:22

标签: c++ templates c++11 constructor type-conversion

给定以下使用std :: array的向量类(用于2d,3d或4d向量数学),是否可以定义可变参数构造函数和/或转换构造函数?

作为一个后续问题,这种事情是不是很糟糕?我发现自己需要转换为整数,浮点数和双精度数。

我知道隐式转换会发生,但我的编译器会给我一些警告(我不想让它们一般关闭)。

#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;
}

3 个答案:

答案 0 :(得分: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))...}} 
    {}
};

答案 1 :(得分: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])...})
    { }

    ...
};

答案 2 :(得分:1)

从您的示例中,我认为提交的值在任何情况下都具有相同的类型。那么,为什么不使用std::initializer_list?此外,您之前将它们转换为T0类型,然后将它们传递给内部std::array,所以也许它值得。实际上你并不关心参数的类型,只要你可以将它们转换为T0