警告C4244:'argument':从'double'转换为'const int',可能会丢失数据

时间:2013-08-31 21:13:27

标签: c++

我正在定义'*'运算符以使用'NumericArray'类模板。代码如下:

template <class T>
NumericArray<T> NumericArray<T>::operator * (const T& factor) const
{
    NumericArray<T> newArray(Size());
    for (int i = 0; i < Size(); i++)
        newArray[i] = factor * GetE(i);
    return newArray;
}

当'factor'参数是double时,我尝试使用'int'(NumericArray)类型的'NumericArray'和'*'运算符:

intArray1 = intArray1*2.5;

我收到以下编译器警告:

warning C4244: 'argument' : conversion from 'double' to 'const int', possible loss of data

并且'factor'arg在与'NumericArray'对象的元素相乘之前从2.5截断到2(一个int)。有没有办法防止这种情况发生?我认为在C ++中它是默认协议的简单问题,其中int * double = double。我错了吗?如果没有,为什么不适用于这种情况?

2 个答案:

答案 0 :(得分:9)

intArray1 = intArray1*2.5;

我猜intArray1的类型为NumericArray<int>。如果是这样,则Tint。因此,在上面的表达式中,作为2.5的{​​{1}}将转换为double,因为它将作为参数传递给重载的int

这也意味着,2.5(双)变为2(整数),operator*(const int&)基本上是factor。丢失数据!

解决此问题的一种方法是使用函数模板(作为类模板的成员):

2

上述定义中对template<class T> //this is for class templatwe template<class U> //this is for function template NumericArray<T> NumericArray<T>::operator * (const U& factor) const { //^^^^^^^ it is U now! //your code } 的两次使用不要感到惊讶。评论说出了他们的意图。如果你理解得那么好,那么你也明白参数 now template而不是U,它可以独立于T因此它可以是无论你把它作为论点传递给它。在通过论证时,不会丢失数据。

现在您知道Tint的产品原来是double,那么为什么在您通过{{1}时从函数返回double它呢?如果参数为NumericArray<int>,我认为返回double会更有意义。所以以下似乎是正确的实现:

NumericArray<double>

<强>等待!这是正确的吗?如果doubletemplate<class T> //this is for class templatwe template<class U> //this is for function template NumericArray<U> NumericArray<T>::operator * (const U& factor) const { //^^^ CHANGED NumericArray<U> newArray(Size()); //CHANGED HERE TOO! for (int i = 0; i < Size(); i++) newArray[i] = factor * GetE(i); return newArray; } Tdouble,该怎么办?以上问题与前一个问题完全相同!

所以这是第三次尝试:

U

所以返回类型是:

int

其中template<class T> //this is for class templatwe template<class U> //this is for function template NumericArray<decltype(std::declval<T>() * std::declval<U>())> NumericArray<T>::operator * (const U& factor) const { typedef decltype(std::declval<T>() * std::declval<U>()) R; //define R NumericArray<R> newArray(Size()); //CHANGED HERE! for (int i = 0; i < Size(); i++) newArray[i] = factor * GetE(i); return newArray; } 是:

NumericArray<R>

取决于Rdecltype(std::declval<T>() * std::declval<U>()); 的产品类型。现在这是正确的,至少好多了。

希望有所帮助。

答案 1 :(得分:-1)

你的模板代码要求参数和NumericArray元素具有相同的时间,这就是为什么C ++在乘法之前将arg截断为2的原因。

要解决此问题,您应该编写类似

的代码
template <class U> template<class T>
NumericArray<T> NumericArray<T>::operator * (const U& factor) const
{
  /***/
}