2016-12-06 15 views
2

OK Matrixクラスの+ =と - =演算子をオーバーロードしたい。
は今、2つの行列を合計または減算するために、我々は両方の行列の各値を反復処理し、加算または減算する必要があるので、それは次のようにいくつかのことになります:あなたは両方の演算子を見ることができるよう、「C++ファンクタの使用、コードの重複回避

Matrix& Matrix::operator+= (const Matrix& M){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] += M[indexR][indexC]; 
} 

Matrix& Matrix::operator-= (const Matrix& M){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] -= M[indexR][indexC]; 
} 

+ = "と" - = "は同じ構造を持っています。つまり、基本的に"ルール "と呼ばれるものは、コードの重複を避けることです。
このような重複を避け、コードを有効にするにはどうすればよいですか?

+0

この小さなコードの複製は実際の問題ではありません。 – Brian

+0

@Brianまあ、それでも私はそれを避けたいと思います。(それは単なる例です...) –

答えて

4

テンプレート化された単一の関数を実装し、2つの呼び出しを行うことができます。

template<typename T> 
Matrix& add_or_sub (const Matrix& M, const T &op){ 
    for (int indexR = 0; indexR < rows; ++indexR) 
     for (int indexC = 0; indexC < cols; ++indexC) 
      Mat_p[indexR][indexC] = op(Mat_p[indexR][indexC], M[indexR][indexC]); 
    return *this; 
} 

Matrix& Matrix::operator+= (const Matrix& M){ 
    return add_or_sub(M, std::plus()); 
} 

Matrix& Matrix::operator-= (const Matrix& M){ 
    return add_or_sub(M, std::minus()); 
} 
+2

4分遅れて...私は2つの音符しかし、。私は 'add_or_sub'と' piecewise_apply'という名前を付けるほうがよいと思います。そして、それがメンバ関数として意図されていれば 'M'または' * this'を返すべきではありませんか? – luk32

+0

@ luk32私はちょうど質問からコードをコピーしました。 P.S. [命名は難しい](http://martinfowler.com/bliki/TwoHardThings.html)。 –

+0

@ MarkRansomありがとう、多くの感謝、私は別の演算子のオーバーロードを追加したいと言うことができると言うことができます* =または*(割り当てなし)スカラーパラメータ(int)で、私はスカラー整数で行列の各ノードを掛けたい。与えられたテンプレートを使って与えられたコードで実装できますか? ありがとうございます。 –

2

私は少し遅れていますが、私はその例がより完全だと思います。私は、基本的なスカラーをオペランドとして使用し、同じ型を返し、これを使用して演算子を実装する、区分的なファンクション・アプリケータを書くことを提案します。

例:それは初期化を欠いて

#include <iostream> 
#include <functional> 
using namespace std; 

template <int Rows, int Cols, typename Scalar = int> 
class Matrix { 
    public: 
    void piecewise_apply(const Matrix& other, std::function<Scalar(Scalar,Scalar)> f) { 
     for (int indexR = 0; indexR < Rows; ++indexR) 
      for (int indexC = 0; indexC < Cols; ++indexC) 
       data[indexR][indexC] = f(data[indexR][indexC], other.data[indexR][indexC]); 
    } 

    Matrix<Rows,Cols,Scalar>& operator+=(const Matrix<Rows,Cols,Scalar>& rhs) { 
     piecewise_apply(rhs, std::plus<Scalar>()); 
     return *this; 
    } 

    Matrix<Rows,Cols,Scalar>& operator-=(const Matrix<Rows,Cols,Scalar>& rhs) { 
     piecewise_apply(rhs, std::minus<Scalar>()); 
     return *this; 
    } 
    private: 
    Scalar data[Rows][Cols]; 
}; 

int main() { 
    Matrix<5,5> a; 
    Matrix<5,5> b; 

    a.piecewise_apply(b, [](int a, int b){return a*b;}); 
    a -= b; 
    return 0; 
} 

例は、完全ではありません。また、&rhs == this(最適化のための興味深い場所)、そしておそらくさらにいくつかの保護がありますが、それはアイデアを示しています。コードの効率性については、よくこのコンパイラに頼るべきです。

デフォルトのバージョンでは少し遅くても、ブロッキングや並列化などのより精巧な最適化手法を使用してさまざまな場所で高速化を実現するpiecewise_applyを書くことができます。

例のように、コピー貼り付けのバージョンが短く分かりやすく、わかりやすいので、おそらく良い選択です。

+0

ニースの回答もありがとう。 –

関連する問題