默认<=>会自动免费提供==, !=, <, >, <=, >=
C++20 有一个新的“默认比较”功能设置,因此默认<=> 可以免费提供所有其他功能。我相信这是添加operator<=>的主要动机。
改编自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);
// All of these are automatically defined for us!
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
上面的等效更明确的版本是:
struct Point {
int x;
int y;
auto operator<=>(const Point& other) const {
if (x < other.x) return -1;
if (x > other.x) return 1;
if (y < other.y) return -1;
if (y > other.y) return 1;
return 0;
}
bool operator==(const Point& other) const = default;
};
在这种情况下,我们需要显式设置bool operator==(const Point& other) const = default;,因为如果operator<=> 没有默认设置(例如,如上所述),那么operator== 不会自动默认设置:
根据任何operator<=> 重载的规则,默认的<=> 重载还允许将类型与<、<=、> 和>= 进行比较。
如果operator<=> 是默认的,而operator== 根本没有声明,那么operator== 是隐式默认的。
上面的例子使用了与默认operator<=>相同的算法,cppreference 解释为:
默认的operator<=>通过依次比较T的基(从左到右深度优先)和非静态成员(按声明顺序)子对象来进行字典比较以计算,递归扩展数组成员(按下标递增的顺序),当发现不相等的结果时提前停止
在 C++20 之前,您不能执行类似 operator== = default 的操作,并且定义一个运算符不会导致定义其他运算符,例如以下无法使用-std=c++17 编译:
#include <cassert>
struct Point {
int x;
int y;
auto operator==(const Point& other) const {
return x == other.x && y == other.y;
};
};
int main() {
Point pt1{1, 1}, pt2{1, 2};
// Do some checks.
assert(!(pt1 == pt2));
assert( (pt1 != pt2));
}
有错误:
main.cpp:16:18: error: no match for ‘operator!=’ (operand types are ‘Point’ and ‘Point’)
16 | assert( (pt1 != pt2));
| ~~~ ^~ ~~~
| | |
| Point Point
上面的代码确实在-std=c++20下编译。
相关:Are any C++ operator overloads provided automatically based on others?
在 Ubuntu 20.04、GCC 10.2.0 上测试。