C++中按引用传递和按值传递之间重载歧义的实用解决方案
Practial solution to overload ambiguity between pass by reference and pass by value in C++
我有一个 class 3d 矢量模板 class 看起来有点像(缩写):
template<typename T>
class vector3
{
public:
typedef vector3<T> self;
self& operator*(T& a);
self& operator*(T a);
T x,y,z;
};
两个 operator* 重载 'self multiply' 向量乘以标量,return *this.
我希望能够像这样使用 class 模板:
vector3<double> vv;
double scalar;
vv*scalar;
vv*0.5;
重载歧义很明显,并且'just get it to work'种解决方案可用并且已在其他SA问题中讨论过。
如果你删除 operator*(T& a),一切都会编译,但是你(至少在理论上),当你真的不需要时,你会失去一些通过值传递的性能优势(对吗?)
如果去掉operator*(T a),就做不到vv*0.5.
如果您重命名其中一个,那么在所有这些操作在数学方面直观上有意义的情况下,您会失去很多代码清晰度。
有没有办法在有意义的时候保留按引用传递,但消除重载歧义?确保 vector3 模板适应上述两个表达式的最佳方法是什么?
只需让另一个采用 rvalue 参考:
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*
应该 return 一个值。 operator*=
应该 return 参考。
最适合您的选择是
self operator * (const T& a) const;
一共有三个瞬间:
使用 const T&
而不是 T
或 T&
。现代编译器很聪明,他们会优化代码并按值而不是引用传递小类型。
运算符*
不应更改操作数。
运算符 *
应该 return 一个值而不是一个引用。
您可以创建一个将右值作为参数的方法,如 Barry 所述。
或者您的模板参数可以是 const
如果实现不修改它。在这种情况下,您可能只有一种方法采用 const
参考:
self operator*(const T& a) const;
我有一个 class 3d 矢量模板 class 看起来有点像(缩写):
template<typename T>
class vector3
{
public:
typedef vector3<T> self;
self& operator*(T& a);
self& operator*(T a);
T x,y,z;
};
两个 operator* 重载 'self multiply' 向量乘以标量,return *this.
我希望能够像这样使用 class 模板:
vector3<double> vv;
double scalar;
vv*scalar;
vv*0.5;
重载歧义很明显,并且'just get it to work'种解决方案可用并且已在其他SA问题中讨论过。
如果你删除 operator*(T& a),一切都会编译,但是你(至少在理论上),当你真的不需要时,你会失去一些通过值传递的性能优势(对吗?)
如果去掉operator*(T a),就做不到vv*0.5.
如果您重命名其中一个,那么在所有这些操作在数学方面直观上有意义的情况下,您会失去很多代码清晰度。
有没有办法在有意义的时候保留按引用传递,但消除重载歧义?确保 vector3 模板适应上述两个表达式的最佳方法是什么?
只需让另一个采用 rvalue 参考:
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*
应该 return 一个值。 operator*=
应该 return 参考。
最适合您的选择是
self operator * (const T& a) const;
一共有三个瞬间:
使用
const T&
而不是T
或T&
。现代编译器很聪明,他们会优化代码并按值而不是引用传递小类型。运算符
*
不应更改操作数。运算符
*
应该 return 一个值而不是一个引用。
您可以创建一个将右值作为参数的方法,如 Barry 所述。
或者您的模板参数可以是 const
如果实现不修改它。在这种情况下,您可能只有一种方法采用 const
参考:
self operator*(const T& a) const;