使用移动语义和完美转发来实现"懒惰"运算符+

Using move semantics and perfect forwarding to implement a 'lazy' operator+

本文关键字:实现 懒惰 运算符 转发 移动 语义 完美      更新时间:2023-10-16

我正在尝试编写一个

friend T operator+( lhs, rhs){
};

现在,我想尽可能避免建造临时的。

例如:

  1. 如果lhsrhsconst T&operator+应该从lhs创建一个temp复制构造,然后temp += rhs;它,最后return std::move(temp)
  2. 如果lhsT&&那么我想直接rhs求和它,如lhs += rhs;,然后return std::move(lhs).这种情况避免了(A+B)+C中的复制构造,因为在表达式外部不需要 (A+B) 的输出。请注意,我们可能必须执行temp(std::move(lhs))才能为这两种情况 1 提供通用代码。和案例 2。
  3. 同样,对于
  4. 其他两种情况,当rhslhsrhsT&&时。

通过编写四个重载,我设法做到了这一点。现在,我已经读到可以利用模板和forward来减少重载的数量,甚至可以只在一个模板函数中编写它。我很难理解如何。

看来我需要

template<typename R, typename S, typename T>
R operator+(S&& lhs, T&& rhs){
   // ...
};

但是我对内容所做的尝试不起作用。

我可能还需要处理一个额外的问题。如果不是operator+我们需要operator-operator/方法的主体,则不一定在所有情况下都相似。在A/B中,如果AT&&我们可以A /= B。但是,如果BT&&的那个,那么我们可能需要做B.reciprocal() *= A .所以,我想我还需要一种方法来知道在模板中输入了哪个案例。

注意:我的乘法可交换的(矩阵中的分量乘法(。

您能否就如何处理这个问题提出一些意见和想法?

给自己和下一个读者的注意事项:指向有关使用表达式模板的一些阅读的链接。

编写一个名为 sum 的函数。 sum 有 3 个重载:lhs&&, rhs const&lhs const&, rhs&&, ... - ...很重要,因为它使它成为最差的匹配,消除了歧义。 最后const& lhs, const& rhs.

然后template<lhs, rhs> auto operator+(lhs&&,rhs&&)->decltype完美的前锋到sum.

一旦你开始工作,我们就可以继续前进。 我们可以为每个运算符重新实现它,也可以提升一个抽象级别。

你有一个变异的二进制运算(+=等(和一个反对称变换(大多数是noop,除法是逆的 - 除法的二进制运算是*=顺便说一句(。 将它们传递给像sum一样超载的调度程序。

对这两个函数对象使用函数对象,重写sum函数以采用increase_mat{}noop{}应该很容易。