5

我正在定义“*”运算符以使用“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;
}

当我尝试在“因子”参数为双精度时将“int”(NumericArray)类型的“NumericArray”与“*”运算符一起使用时:

intArray1 = intArray1*2.5;

我收到以下编译器警告:

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

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

4

2 回答 2

9
intArray1 = intArray1*2.5;

我猜intArray1是类型NumericArray<int>。如果是这样,那么T就是int。所以在上面的表达式中,2.5adouble将被转换为int,因为它operator*(const int&)作为参数传递给重载。

这也意味着 2.5 (double) 变成 2 (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
}

不要template对上述定义中的两个用法感到惊讶。评论说明了它们的用途。如果你理解得很好,那么你也明白参数现在U而不是T,它可以独立于T,因此它可以是你作为参数传递给它的任何东西。只要传递参数,就不会丢失数据。

int现在你知道和的乘积doubledouble,那么为什么NumericArray<int>要从函数返回以防万一你传递double给它呢?NumericArray<double>我认为如果参数是return 更有意义double。所以以下似乎是正确的实现:

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

等待!现在这正确吗?如果TisdoubleUisint怎么办?上面的问题和上一个完全一样!

所以这是第三次尝试:

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>

哪里R是:

decltype(std::declval<T>() * std::declval<U>());

这取决于 和 的产品T类型U。现在是正确的,至少好多了。

希望有帮助。

于 2013-08-31T21:16:35.930 回答
-1

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

要解决这个问题,您应该编写类似的代码

template <class U> template<class T>
NumericArray<T> NumericArray<T>::operator * (const U& factor) const
{
  /***/
}
于 2013-08-31T21:20:54.470 回答