C ++仿函数用法,避免代码重复

时间:2016-12-06 21:52:31

标签: c++ functor code-duplication

好吧所以我不确定它是否与仿函数有关,但是从我的理解是如此 问题是: 我假设我有下一堂课:

class Matrix{
public:
    Matrix(int, int);                       // constructor
    Matrix(const Matrix&);                  // copy constructor

    Matrix& operator+= (const Matrix&);
    Matrix& operator-= (const Matrix&);
    int* operator[] (int) const;

private:
    int rows;
    int cols;
    int** Mat_p;
};

我希望重载Matrix类中的+ =和 - =运算符 现在,为了求和或减去2个矩阵,我们需要迭代两个矩阵的每个值并加或减,这样就可以了:

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

正如您所看到的那样,运算符“+ =”和“ - =”具有相同的结构,因此所谓的“规则”之一就是避免代码重复。
所以问的问题是我们如何避免这种重复并使代码保持有效?

2 个答案:

答案 0 :(得分:4)

你可以实现一个模板化函数并对其进行两次调用。

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

答案 1 :(得分: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,它使用更精细的优化技术,如阻塞或并行化等,并获得加速各地。

对于简单版本,如您的示例,复制粘贴版本更短,更容易理解,因此可能是更好的选择。