可变模板和初始值设定项列表的类型缩小差异

variadic templates and initializer lists type narrowing differences

本文关键字:列表 类型 缩小      更新时间:2023-10-16

所以这没有任何意义。

此类:

template< typename T, int nDimensions = 2 >
class Vec {
private:
std::array< T, nDimensions > elements_;
public:
typedef T ValueType;
Vec() : elements_() {}
template <typename... U>
Vec(U... ts) : elements_{ ts... } {}
Vec(const std::initializer_list<T>& values){
std::copy(values.begin(), values.end(), elements_.begin());
}
template <typename T2, int nDimension2>
Vec(Vec<T2, nDimension2> const& copy){
for (int i = 0; i < nDimensions; i++){
this->elements_[i] = (T)static_cast<T2>(copy[i]);
}
}
};

为什么做起来很好:

Vec<int,2> twoi = { 1, 2.1 }; //An int and a double

但不是:

Vec<int,2> twoi2(1,2.1); //conversion from 'double' to 'int' requires a narrowing conversion

这似乎并不直观。对于Initializer列表,它只是预成型转换,而另一方面,当模板展开时,它应该只交出转换为int的double。

如果我是正确的,这也是功能应该扩展的:

std::array< int, 2> elements_ = { 1.2,1};

它编译得很好。

有没有办法修改这个构造函数来忽略转换?

Visual Studios 2015更新3版本:

1>------ Build started: Project: MathTests, Configuration: Debug Win32 ------
1>  Source.cpp
1>d:projectsstevenstuffmathtestssource.cpp(12): warning C4838: conversion from 'double' to 'int' requires a narrowing conversion
1>d:projectsstevenstuffmathtestssource.cpp(12): warning C4244: 'initializing': conversion from 'double' to 'int', possible loss of data
1>d:projectsstevenstuffutilvecincludevec.h(19): error C2397: conversion from 'const double' to 'int' requires a narrowing conversion
1>  d:projectsstevenstuffmathtestssource.cpp(10): note: see reference to function template instantiation 'Vec<int,2>::Vec<double,int>(const double &,const int &)' being compiled

最终解决了这个问题。

简单的答案是,需要进行转换。有些编译器对它很满意,只是直接进行强制转换,有些则不然,并抱怨这是不可能的。绕过它的方法是将一个狡猾的类型转换到构造函数中。

template <typename... U>
Vec(const U&... ts) 
: elements_{(T)(ts)... } {
}

然后一切展开为:elements_((T)ts[1]。。。外部