C++ 可变用户定义转换/构造函数

C++ 可变用户定义转换/构造函数,c++,templates,c++11,constructor,type-conversion,C++,Templates,C++11,Constructor,Type Conversion,给定以下使用std::array的向量类(用于2d、3d或4d向量数学),是否可以定义可变构造函数和/或转换构造函数 作为一个后续问题,这种做法是否不好?我发现自己需要大量地从整数、浮点和双精度转换 我知道会发生隐式转换,但我的编译器会对此发出警告(我一般不想关闭它们) #包括 模板 Vec类 { 公众: 静态断言(S>1&&S1&&S

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

作为一个后续问题,这种做法是否不好?我发现自己需要大量地从整数、浮点和双精度转换

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

#包括
模板
Vec类
{
公众:
静态断言(S>1&&S<5,“向量维数必须介于2和4之间”);
静态_断言(std::is_算术::value,“类型必须是算术的”);
std::数组v;
Vec()=默认值;
模板
Vec(T1,T2):v({static_cast(T1)),
静态_-cast(t2)}{
模板
Vec(T1,t2t2,t3t3):v({static_cast(T1)),
静态浇铸(t2),
静态_cast(t3)}{}
模板
Vec(T1,t2t2,t3t3,t4t4):v({static_cast(T1)),
静态浇铸(t2),
静态浇铸(t3),
静态_-cast(t4)}{
};
内部主(空)
{
自动foo1=Vec(1,2);
自动foo2=Vec(1.0f,2.0f);
自动foo3=Vec(1.0,2.0);
自动foo4=Vec(1u,2u);
返回0;
}

当然有可能

顺便说一句,在这种情况下,您不需要默认构造函数,因为这种可变构造函数在某种程度上更好,它将使您的数组归零

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))...}} 
    {}
};
模板
Vec类
{
公众:
静态断言(S>1&&S<3,“向量维数必须介于2和4之间”);
静态_断言(std::is_算术::value,“类型必须是算术的”);
std::数组v;
模板
Vec(T&…a):v{{static_cast(std::forward(a))…}
{}
};

根据您的示例,我认为提交的值在任何情况下都具有相同的类型。那么,为什么不使用
std::initializer\u list
?此外,您将它们强制转换为之前的类型
T0
,以将它们传递给内部
std::array
,因此这可能是值得的。实际上,您并不关心参数的类型,只要您向类模板添加索引序列,就可以将它们强制转换为
T0

template<typename T0, size_t S, typename = std::make_index_sequence<S>>
class Vec;
模板
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])...})
    { }

    ...
};
模板
Vec类
{
使用ith_T=T0的模板;
...
Vec(第…页)
:v({ts..})//不需要强制转换,它们已经是T0了
{ }
模板
车辆主管(施工车辆主管和右主管)
:v({static_cast(rhs.v[Idx])…})
{ }
...
};

哦,这太聪明了。非常感谢。我想我需要升级:“错误C2797:'Vec::v':成员初始值设定项列表或非静态数据成员初始值设定项中的列表初始化未实现”注意:对于使用VS 2013的任何人,这将编译“Vec(T1&&…a):v({static_cast(a)…}){}”,它们通常具有相同的类型,但有时没有。从例子中不清楚。不管怎样,事实上你对他们的类型并不感兴趣。你不能利用这个机会吗?你收到的所有回复都是在利用这个事实,不是吗?诚实并不是最重要的。事实上,不是问题不太清楚,就是我误解了。对不起。:-)关于模板参数S的静态断言似乎很奇怪。如果它必须大于1小于3,那么你可以说它必须是2。谢谢。修好了。2、3或4。
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])...})
    { }

    ...
};