c++中操作符重载需要写多种重复版本(引用与右值引用),有无方法可以简化

发布于 2022-09-04 18:50:26 字数 483 浏览 26 评论 0

例如:

mat33 operator +(mat33& m1, mat33& m2);
mat33 operator -(mat33& m1, mat33& m2);
mat33 operator +(mat33&& m1, mat33&& m2);
mat33 operator -(mat33&& m1, mat33&& m2);
mat33 operator +(mat33&& m1, mat33& m2);
mat33 operator -(mat33&& m1, mat33& m2);
mat33 operator +(mat33& m1, mat33&& m2);
mat33 operator -(mat33& m1, mat33&& m2);

有无什么方法可以简化这一大串?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

层林尽染 2022-09-11 18:50:26

如果你想要减少声明的次数,那是有办法的,简化代码似乎不可能。按照你的声明思路,&&,&&&&,&可以将工作代理给&,&&。这样代码不复杂,也没有重复。

这里至少需要两个实现,其中一个移动数据,另一个不移动数据。移动数据分lhs和rhs。同时还要兼顾ADL。实现这些至少需要声明三个重载。用模板可以将声明减少到两个:

template <class T>
std::enable_if_t<std::is_convertible<T, mat33>::value, mat33>
operator+(T &&, const mat33 &) {
  if (std::is_rvalue_reference<T &&>::value && !std::is_const<T>::value) {
    std::cout << "move from lhs" << std::endl;
  } else {
    std::cout << "no move" << std::endl;
  }
  return {};
}

template <class T>
inline mat33 operator+(T &&lhs, mat33 &&rhs) {
  std::cout << "rhs -> lhs, ";
  return std::move(rhs)+lhs;
}

PS: c++17后可以用constexpr if实现静态分枝。c++17之前编译器也通常可以完成这样的优化。

测试代码:

#include <utility>
#include <type_traits>
#include <iostream>

namespace detail {

struct mat33 {};

template <class T>
std::enable_if_t<std::is_convertible<T, mat33>::value, mat33>
operator+(T &&, const mat33 &) {
  if (std::is_rvalue_reference<T &&>::value && !std::is_const<T>::value) {
    std::cout << "move from lhs" << std::endl;
  } else {
    std::cout << "no move" << std::endl;
  }
}

template <class T>
inline mat33 operator+(T &&lhs, mat33 &&rhs) {
  std::cout << "rhs -> lhs, ";
  return std::move(rhs)+lhs;
}

} // namespace detail


int main() {
  detail::mat33 a, b;
  const detail::mat33 ca, cb;
  
  // move from lhs
  std::move(a)+b;
  std::move(a)+cb;
  
  // rhs -> lhs, move from lhs
  a+std::move(b);
  ca+std::move(b);

  // no move
  a+b;

  ca+cb;
  std::move(ca)+cb;
  ca+std::move(cb);

  a+cb;
  ca+b;
  std::move(ca) + b;
  a + std::move(cb);

  return 0;
}
提赋 2022-09-11 18:50:26
mat33 operator +(const mat33& m1, const mat33& m2);
mat33 operator -(const mat33& m1, const mat33& m2);

不就搞定了。。。
const & 能匹配所有引用(左值、右值、常量左值、常量右值)。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文