C++仿函数的使用,避免代码重复
C++ functors usage, code duplication avoidance
好的,所以我不确定它是否与仿函数有关,但据我了解是这样
问题是:
假设我有下一个 class:
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 class.
中重载 += 和 -= 运算符
现在,为了对 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];
}
如您所见,运算符“+=”和“-=”具有相同的结构,所以所谓的 "rules" 之一是避免代码重复。
所以问的问题是我们如何避免这种重复并保持代码有效?
您可以实现一个模板化函数并对其进行两次调用。
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());
}
我来晚了一点,但我想这个例子更完整了。我建议编写一个分段仿函数应用程序,它使用底层标量作为操作数,returns 也是相同的类型,并使用它来实现运算符。
一个例子:
#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
,它使用更精细的优化技术,如阻塞或并行化等,并得到多处加速。
对于简单版本,如您的示例,复制粘贴版本更短,更容易理解,因此可能是更好的选择。
好的,所以我不确定它是否与仿函数有关,但据我了解是这样 问题是: 假设我有下一个 class:
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 class.
中重载 += 和 -= 运算符
现在,为了对 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];
}
如您所见,运算符“+=”和“-=”具有相同的结构,所以所谓的 "rules" 之一是避免代码重复。
所以问的问题是我们如何避免这种重复并保持代码有效?
您可以实现一个模板化函数并对其进行两次调用。
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());
}
我来晚了一点,但我想这个例子更完整了。我建议编写一个分段仿函数应用程序,它使用底层标量作为操作数,returns 也是相同的类型,并使用它来实现运算符。
一个例子:
#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
,它使用更精细的优化技术,如阻塞或并行化等,并得到多处加速。
对于简单版本,如您的示例,复制粘贴版本更短,更容易理解,因此可能是更好的选择。