[英]Arithmetic compound operator overload as non-member
I've written a templated class that implements some basic operator overloading, following the guidelines provided by this particularly insightful answer : 我按照这个特别有见地的答案提供的指导方针,编写了一个模板类,该类实现一些基本的运算符重载:
template <typename _type>
class myClass {
// ...
template<_input_type> myClass<_type>& operator+=(const myClass<_input_type>& _other);
// ...
}
with the arithmetic compound operators written as members: 将算术复合运算符写为成员:
template <typename _type>
template <typename _input_type>
myClass<_type>& myClass<_type>::operator+=(const myClass<_input_type>& _other) {
static_assert(std::is_arithmetic<_type>::value);
// do stuff
return *this;
};
and the non-compound operator as a non-member: 非复合运算符作为非成员:
template <typename _type, typename _input_type>
inline myClass<_type> operator+(myClass<_type>& _o1, myClass<_input_type> _o2) {
return _o1+=_o2;
};
However, due to the template myClass
can be used for several data types, some of them non-numeric that can't handle +
, -
, *
or /
operators, and as such I was wondering what are the downsides of implementing all operator overloading code as non-member functions, so that eg I could just placed them all on a separate header file that would only need to be included if there is need for arithmetic functionality. 但是,由于模板myClass
可用于多种数据类型,其中一些非数字类型无法处理+
, -
, *
或/
运算符,因此我想知道实现所有运算符重载的不利之处代码作为非成员函数,因此例如我可以将它们全部放在单独的头文件中,仅在需要算术功能时才需要将其包括在内。 I understand one solution would be to define a new class myNumericClass : public myClass
that just implements operator overloading, but that would require a new typename and limit the versatility of myClass
. 我知道一种解决方案是定义一个新class myNumericClass : public myClass
, class myNumericClass : public myClass
仅实现运算符重载,但是这需要一个新的typename并限制myClass
的多功能性。
The primary shortcoming of implementing compound assignment as a non-member is inconsistency with the simple (copy or move) assignment operator. 将复合分配作为非成员实现的主要缺点是与简单的(复制或移动)分配运算符不一致。 A simple copy or move assignment (ie, operator=
) must be implemented as a member function, or the compiler will outright reject the code. 一个简单的复制或移动分配(即, operator=
) 必须被实现为一个成员函数,或编译器将直接拒绝的代码。
Given that copy/move assignment must be implemented as member functions, many prefer to implement compound assignment as members as well. 鉴于必须将复制/移动分配实现为成员函数,因此许多人也希望将复合分配也实现为成员。
As an aside, this code: 顺便说一句,此代码:
template <typename _type, typename _input_type>
inline myClass<_type> operator+(myClass<_type>& _o1, myClass<_input_type> _o2) {
return _o1+=_o2;
};
...is, IMO, highly inadvisable. ……是国际海事组织(IMO)的,非常不可取的。 The general style is fine, but you've mixed up which operand to pass by value and which to pass by reference. 通用样式很好,但是您混淆了要按值传递哪个操作数和按引用传递哪个操作数。 As a result, it may be needlessly inefficient, and (much worse) modifies its left operand, so it really acts like +=
instead of +
. 结果,它可能不必要地效率低下, 并且 (更糟的是)修改了它的左操作数,因此它的行为实际上类似于+=
而不是+
。 What you almost certainly want is more like this: 您几乎肯定想要的是这样的:
template <typename _type, typename _input_type>
inline myClass<_type> operator+(myClass<_type> _o1, myClass<_input_type> const &_o2)
{
return _o1+=_o2;
};
Here we pass the left operand by value, so when the function is called a temporary value is created and initialized from the left operand. 在这里,我们按值传递左操作数,因此在调用该函数时,会从左操作数创建并初始化一个临时值。 We then modify that temporary value ( without changing the original) and return it. 然后,我们修改该临时值( 不更改原始值)并返回它。 Since we do return it, there will be copy elision (optional on older compilers, but mandatory since C++17) which means it'll normally really just be a reference to the destination, so effectively, something like: a = b + c;
由于我们确实返回了它,所以会有复制省略号(在旧的编译器上是可选的,但是自C ++ 17起是必需的),这意味着它通常实际上只是对目标的引用,因此有效地类似于: a = b + c;
will be treated as: a = b; a += c;
将被视为: a = b; a += c;
a = b; a += c;
. 。 Since we only need the previous value of the right operand, we pass it as a reference to const to avoid an unnecessary copy (though, depending on the type, passing by reference may not gain enough to care about, or could even be a loss. But it can be a big gain, and is rarely more than a tiny loss). 由于我们只需要右操作数的前一个值,因此我们将其作为对const的引用来避免不必要的复制(尽管根据类型的不同,按引用传递可能不会获得足够的关注,甚至可能会造成损失但它可以带来很大的收益,而且损失很少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.