如何在不违反C++中的DRY原则的情况下实现可移动重载?
how to implement movable overloads without violating the DRY principle in C++?
在我的一些 类 中实现方法和运算符重载以利用 C++ 中的右值引用时,我经常编写一些设计不佳的代码,违反了 DRY 原则。下面的代码片段有什么更好的替代方案? (这段代码只是为了说明问题)
class matrix_2_2
{
int _m[2][2];
public:
matrix_2_2 operator*(const matrix_2_2& m) const &
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < 2 ; j++)
for(int k = 0 ; k < 2 ; k++)
res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);
return res;
}
matrix_2_2 operator*(matrix_2_2&& m) &&
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < 2 ; j++)
for(int k = 0 ; k < 2 ; k++)
res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);
return move(res);
}
这段代码在实现细节上出现了很多重复,我想封装逻辑并在不同的重载中重用它,而不会因为右值到左值的隐式转换而失去可移动的优势。
一个更好的选择是完全删除右值限定的 operator*
并且只有一个 operator*
,这个:
matrix_2_2 operator*(const matrix_2_2& m) const;
您的 class 是一个 POD - 在这种情况下,移动和复制之间没有区别,因此您不可能通过利用移动语义来获得优势。您获得了代码复杂性,但没有获得性能。如果 this
是 &
或 &&
...
,那么您的代码应该执行的操作在逻辑上确实没有区别
另外,这个:
matrix_2_2 operator*(matrix_2_2&& m) &&
{
matrix_2_2 res;
...
return std::move(res);
}
不是正确的写法,因为最后一个 move
使得无法进行命名的 return 值优化,所以你正在做一个额外的 move
代码如:
matrix_2_2 product = some_matrix() * some_other_matrix();
而不是简单地在 product
中就地构建 res
。
在我的一些 类 中实现方法和运算符重载以利用 C++ 中的右值引用时,我经常编写一些设计不佳的代码,违反了 DRY 原则。下面的代码片段有什么更好的替代方案? (这段代码只是为了说明问题)
class matrix_2_2
{
int _m[2][2];
public:
matrix_2_2 operator*(const matrix_2_2& m) const &
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < 2 ; j++)
for(int k = 0 ; k < 2 ; k++)
res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);
return res;
}
matrix_2_2 operator*(matrix_2_2&& m) &&
{
matrix_2_2 res;
for(int i = 0 ; i < 2 ; i ++)
for(int j = 0 ; j < 2 ; j++)
for(int k = 0 ; k < 2 ; k++)
res._m[i][j] = (res._m[i][j] + _m[i][k]*m._m[k][j]);
return move(res);
}
这段代码在实现细节上出现了很多重复,我想封装逻辑并在不同的重载中重用它,而不会因为右值到左值的隐式转换而失去可移动的优势。
一个更好的选择是完全删除右值限定的 operator*
并且只有一个 operator*
,这个:
matrix_2_2 operator*(const matrix_2_2& m) const;
您的 class 是一个 POD - 在这种情况下,移动和复制之间没有区别,因此您不可能通过利用移动语义来获得优势。您获得了代码复杂性,但没有获得性能。如果 this
是 &
或 &&
...
另外,这个:
matrix_2_2 operator*(matrix_2_2&& m) &&
{
matrix_2_2 res;
...
return std::move(res);
}
不是正确的写法,因为最后一个 move
使得无法进行命名的 return 值优化,所以你正在做一个额外的 move
代码如:
matrix_2_2 product = some_matrix() * some_other_matrix();
而不是简单地在 product
中就地构建 res
。