假设我正在编写一个int
包装器,并且需要提供每个操作符重载。作者必须列出每一个单独的,或者它可以自动生成任何基于作者所提供的?编译器是否可以从现有的操作符中推断出任何新的自定义操作符?
如果我定义了operator==
,它会自动给我一个operator!=
吗?反之亦然?
如果我定义了operator++()
,我是否可以免费获得operator++(int)
?反之亦然?
+=
类型的业务呢?是否可以将现有的operator+
和operator=
的定义结合起来生成operator+=
?从理论上讲,这应该是可能的,但事实是这样吗?
同样的问题对于>=
到<
等,或者我必须完全列出>
, >
, >=
, <=
的定义吗?
在核心语言中,各种操作符是独立的。有些操作符是根据其他操作符定义的,但如果操作符调用的重载解析失败,则不会尝试用其他操作符表示该调用。当需要时,程序员可以很容易地表达它(相反,关闭这种机制可能会更困难)。
在std::rel_ops
中有一组客户端代码可以使用的关系操作符重载,它们是根据<
和==
定义的。
可以很容易地编写一个mixin类,它根据<
和==
或三值compare
函数提供关系运算符。这就是奇怪循环模板模式的最初动机,称为Barton-Nackman技巧。
No.
c++在核心语言中没有推理规则,所以即使定义说+
,它也不假设+=
…它们(就语言而言)完全无关。
考虑标准库中的<<
(左位移位操作符)被重载为表示"输出到流"…只是因为它的外观和合理的优先级和结合性。
C + + 20运营商<=>
似乎在c++ 20中,std::rel_ops
已被弃用,默认的<=>
将自动免费提供==, !=, <, >, <=, >=
。
改编自https://en.cppreference.com/w/cpp/language/default_comparisons:
main.cpp
#include <cassert>
#include <compare>
#include <set>
struct Point {
int x;
int y;
auto operator<=>(const Point&) const = default;
};
int main() {
Point pt1{1, 1}, pt2{1, 2};
// Just to show it Is enough for `std::set`.
std::set<Point> s;
s.insert(pt1);
// Do some checks.
assert(!(pt1 == pt2));
assert( (pt1 != pt2));
assert( (pt1 < pt2));
assert( (pt1 <= pt2));
assert(!(pt1 > pt2));
assert(!(pt1 >= pt2));
}
编译并运行:
sudo apt install g++-10
g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
更多细节见:What is the <=>c++中的操作符?
在Ubuntu 20.04, GCC 10.2.0上测试
c++ 20增加了一个特性,允许语言对关系运算符(<
, >
, <=
, >=
)和相等运算符(==
和!=
)执行类似的操作。
当使用相等操作符时,系统可以尝试反转操作数的顺序(用于不同类型的相等性测试),也可以为结果取反,以找到合适的operator==
过载。也就是说,如果你只实现operator==
对A
和B
的相等性测试,这也将允许你对B
和A
进行相等性测试,以及对它们进行不等性测试。
==
运算符,它将b != a
转换为!(a == b)
。
对于<=>
,它以相同的方式应用于所有关系操作符(但不是相等操作符)。系统将根据需要将a < b
重写为(a <=> b) < 0
或(b <=> a) > 0
,以找到匹配的重载<=>
操作符。
此外,您可以= default
任何比较操作符,它按照子对象的顺序对所讨论的类型的子对象进行比较(您只能默认对同一类型的比较)。如果您默认使用==
操作符,那么根据上述规则,您将有效地获得!=
。如果默认为<=>
,则可以通过重写获得所有关系操作符。
如果你默认<=>
而不默认==
,那么系统也会生成一个默认的==
,所以默认的<=>
单独给你所有的比较运算符。