c++中按引用传递和按值传递之间重载歧义的实用解决方案

Practial solution to overload ambiguity between pass by reference and pass by value in C++

本文关键字:歧义 解决方案 重载 之间 按引用传递 按值传递 c++      更新时间:2023-10-16

我有一个3d矢量类的类模板,看起来有点像(缩写):

template<typename T>
class vector3
{
public:
  typedef vector3<T> self;
  self& operator*(T& a);
  self& operator*(T a);
  T x,y,z;
};

两个操作符*都重载向量与标量的"自乘法",并返回*this。

我希望能够像这样使用类模板:

vector3<double> vv;
double scalar;
vv*scalar;
vv*0.5;

重载歧义是明确的,"让它工作"的解决方案是可用的,并且已经在其他SA问题中讨论过。

如果删除操作符*(T&A),一切都可以编译,但你(至少在理论上),失去了一些性能优势传递值当你真的不需要(对吗?)

如果去掉操作符*(ta),就不能做vv*0.5。

如果你重命名其中的一个,在所有这些操作直观上有意义的情况下,你会失去很多代码的清晰度。

是否有任何方法在有意义的情况下保留引用传递,但消除重载歧义?确保vector3模板容纳上述两个表达式的最佳方法是什么?

你最好的选择是

self operator * (const T& a) const;

有三个时刻:

  1. const T&代替TT&。现代编译器很聪明,它们会优化代码,并通过值而不是引用传递小类型。

  2. 操作符*不能改变操作数

  3. 操作符*应该返回一个值而不是一个引用

让另一个取右值引用:

self operator*(T& a);   // for 'scalar'
self operator*(T&& a);  // for 0.5

虽然,你真的有一个不同的operator*实现两种不同的情况?你可能只需要:

template <typename U,
          typename = std::enable_if_t<std::is_same<std::decay_t<U>, T>::value>>
self operator*(U&& a);  // for both

注意operator*应该返回一个值。operator*=应该返回一个引用。

您可以像Barry描述的那样创建一个以右值为参数的方法。

或者你的模板参数可以是const,如果实现没有修改它。在这种情况下,您只能有一个方法接受const引用:

self operator*(const T& a) const;
相关文章: