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

「factor」引数が double の場合に、「*」演算子を使用して「int」型 (NumericArray) の「NumericArray」を使用しようとすると、次のようになります。

intArray1 = intArray1*2.5;

次のコンパイラ警告が表示されます。

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

また、'factor' 引数は、'NumericArray' オブジェクトの要素に対して乗算される前に、2.5 から 2 (int) に切り捨てられます。これを防ぐ方法はありますか?C++ では、int*double = double というデフォルト プロトコルの単純な問題だと思いました。私が間違っている?そうでない場合、なぜこの場合に当てはまらないのでしょうか?

4

2 に答える 2

9
intArray1 = intArray1*2.5;

intArray1タイプだと思いNumericArray<int>ます。もしそうなら、Tですint。したがって、上記の式では、引数としてオーバーロードされた に渡されるため、2.5adoubleが に変換されます。intoperator*(const int&)

つまり、2.5 (double) は 2 (int) になり、factor基本的に2. データの損失!

これを修正する 1 つの方法は、(クラス テンプレートのメンバーとして) 関数テンプレートを次のように使用することです。

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上記の定義で が2 つ使用されていることに驚かないでください。コメントは、その目的を示しています。それをよく理解していれば、パラメータではUなく にTなり、 から独立しTているため、引数として渡すものは何でもよいことも理解できます。引数を渡す限り、データの損失はありません。

intとの積が であることがわかっているdoubleので、関数に渡すときに関数からdouble戻るのはなぜですか? 引数が の場合に返す方が理にかなっていると思います。したがって、以下正しい実装のようです。NumericArray<int>doubleNumericArray<double>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;
}

待って!これは今正しいですか?とがの場合Tはどうdoubleなりますか? 上記は前のものとまったく同じ問題を抱えています!Uint

したがって、ここに 3 番目の試みがあります。

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 に答える