我正在添加新的运算符重载以利用 c++0x 右值引用,我觉得我正在生成大量冗余代码。
我有一个类 tree
,它包含一个对 double 值进行代数运算的树。这是一个示例用例:
tree x = 1.23;
tree y = 8.19;
tree z = (x + y)/67.31 - 3.15*y;
...
std::cout << z; // prints "(1.23 + 8.19)/67.31 - 3.15*8.19"
对于每个二元运算(如加号),每一边都可以是左值 tree
、右值 tree
或 double
。这导致每个二元操作有 8 个重载:
// core rvalue overloads for plus:
tree operator +(const tree& a, const tree& b);
tree operator +(const tree& a, tree&& b);
tree operator +(tree&& a, const tree& b);
tree operator +(tree&& a, tree&& b);
// cast and forward cases:
tree operator +(const tree& a, double b) { return a + tree(b); }
tree operator +(double a, const tree& b) { return tree(a) + b; }
tree operator +(tree&& a, double b) { return std::move(a) + tree(b); }
tree operator +(double a, tree&& b) { return tree(a) + std::move(b); }
// 8 more overloads for minus
// 8 more overloads for multiply
// 8 more overloads for divide
// etc
对于每个二元运算(减、乘、除等),也必须以某种方式重复。
如您所见,我实际上只需要编写 4 个函数;其他 4 个可以转换并转发到核心案例。
您对减小这段代码的大小有什么建议吗?
PS:这个类实际上比一个 double 树更复杂。减少拷贝确实显着提高了我的项目的性能。所以,右值重载对我来说是值得的,即使有额外的代码。我怀疑可能有办法模板化上面的“cast and forward”案例,但我似乎想不出任何东西。
最佳答案
只是一个较晚的答案:如果所讨论的类是可移动的,那么移动非常便宜,并且如果可以的话,您总是会从所有参数中移动,那么按值传递参数可能是一种选择:
tree operator +(tree a, tree b);
如果树是可移动的并且一个右值引用作为实际参数传递,那么函数的参数将尽可能使用树的移动构造函数进行初始化,否则使用复制构造函数。然后,该函数可以用它的参数以适当的方式做任何它想做的事情(比如,移动它们的内部)。
与很多重载版本相比,在传递右值引用参数时确实会产生额外的 Action ,但我认为它通常更好。
此外,IMO,tree &&
参数可能应该通过临时拷贝接受左值,但这不是任何编译器目前所做的,所以它不是很有用。
关于c++ - 添加新的 c++0x 右值引用运算符重载时如何减少冗余代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2696156/