如何在添加新的c ++ 0x rvalue引用运算符重载时减少冗余代码

Inv*_*rse 19 c++ operator-overloading rvalue-reference c++11

我正在添加新的运算符重载以利用c ++ 0x rvalue引用,我觉得我正在生成大量冗余代码.

我有一个类,tree它在双值上包含一个代数运算树.这是一个示例用例:

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"
Run Code Online (Sandbox Code Playgroud)

对于每个二元运算(如加号),每一方可以是左值tree,右值treedouble.这导致每个二进制操作有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
Run Code Online (Sandbox Code Playgroud)

这也必须以每种二进制操作(减号,乘法,除法等)的方式重复.

正如您所看到的,实际上我只需要编写4个函数; 其他4个可以转发并转发到核心案例.

您对减少此代码的大小有什么建议吗?

PS:这个类实际上比一个双打树更复杂.减少副本确实可以显着提高项目的性能.因此,即使使用额外的代码,rvalue重载对我来说也是值得的.我有一个怀疑,有可能是一种方式模板走了"的演员和转发"上面的情况,但我似乎无法想象的事情.

Dou*_*oug 7

只是一个快速的回答:如果有问题的类是可移动的,那么移动非常便宜,如果可以,你总是会从所有参数中移出,然后按值传递参数可能是一个选项:

tree operator +(tree      a, tree      b);
Run Code Online (Sandbox Code Playgroud)

如果树是可移动的并且rvalue ref作为实际参数传递,那么函数的参数将在可能的情况下使用树的移动构造函数初始化,否则复制构造函数.然后,函数可以以适当的方式对其参数执行任何操作(例如,移动其内部).

当传递rvalue引用参数与lot-of-overloads版本相比时,它会产生额外的移动,但我认为它通常更好.

此外,IMO,tree &&参数应该可以通过临时副本接受左值,但这不是任何编译器目前所做的,所以它不是很有用.

  • +1,Rvalue引用按值传递返回样式 (2认同)