q-l*_*l-p 200 c++ operators c++-faq spaceship-operator c++20
当我试图了解C++运算符时,我偶然发现cppreference.com上的一个奇怪的比较运算符,*在一个如下所示的表中:

"好吧,如果这些是C++中常见的操作符,我会更好地学习它们",我想.但我所有试图阐明这个谜团的尝试都没有成功.即使在这里,在Stack Overflow上我的搜索也没有运气.
如果有的话,这个运营商到底做了什么?
*与此同时,cppreference.com更新了该页面,现在包含有关<=>运营商的信息.
msc*_*msc 170
这称为三向比较运算符.
根据P0515文件提案:
有一个新的三向比较运算符,
<=>.表达式a <=> b返回一个对象,该对象比较<0ifa < b,compare>0ifa > b和compare==0ifa和b等于/等效.要为您的类型编写所有比较,只需写入
operator<=>返回适当的类别类型:
返回的_ordering如果你的类型自然地支持
<,我们将有效地产生<,>,<=,>=,==,和!=; 否则返回_equality,我们将有效地生成 ==和!=.如果您的类型
a == b暗示f(a) == f(b)(可替换性,其中f只读取比较 - 使用非私有const接口可访问的显着状态),则返回强,否则返回弱.
该cppreference说:
三向比较运算符表达式具有形式
Run Code Online (Sandbox Code Playgroud)lhs <=> rhs (1)表达式返回一个对象
- 比较
<0如果lhs < rhs- 比较
>0如果lhs > rhs- 并比较
==0iflhs和rhs是否相等/等价.
q-l*_*l-p 110
在2017-11-11,ISO C++委员会采用了 Herb Sutter关于<=>"太空船"三向比较运算符的提议,作为添加到C++ 20中的新功能之一.在题为Consistent comparison Sutter 的文章中,Maurer和Brown展示了新设计的概念.有关该提案的概述,以下是该文章的摘录:
表达式a <=> b返回一个对象,如果a <b则比较<0,如果> b则比较> 0,如果a和b等于/等于,则比较== 0.
常见情况:要使用类型Y为类型X编写所有比较,使用成员语义,只需写:
Run Code Online (Sandbox Code Playgroud)auto X::operator<=>(const Y&) =default;晚期病例:要写出你的类型所有比较X型Ÿ,只写操作<=>,需要一个Ÿ,可以使用 =默认获取如果需要按成员的语义,并返回相应的类别类型:
- 如果你的类型自然支持<,则返回_ordering,我们将有效地生成对称<,>,<=,> =,==和 != ; 否则返回_equality,我们将有效地生成对称==和!=.
- 返回strong_如果你的类型a == b暗示f(a)== f(b)(可替代性,其中f只读取使用公共const成员可访问的比较显着状态),否则返回 weak_.
五个比较类别被定义为std::类型,每个类型具有以下预定义值:
+--------------------------------------------------------------------+
| | Numeric values | Non-numeric |
| Category +-----------------------------------+ |
| | -1 | 0 | +1 | values |
+------------------+------+------------+---------------+-------------+
| strong_ordering | less | equal | greater | |
| weak_ordering | less | equivalent | greater | |
| partial_ordering | less | equivalent | greater | unordered |
| strong_equality | | equal | nonequal | |
| weak_equality | | equivalent | nonequivalent | |
+------------------+------+------------+---------------+-------------+
Run Code Online (Sandbox Code Playgroud)
这些类型之间的隐式转换定义如下:
strong_ordering与值{ less,equal,greater}隐式转换为:
weak_ordering用值{ less,equivalent,greater}partial_ordering用值{ less,equivalent,greater}strong_equality用值{ unequal,equal,unequal}weak_equality用值{ nonequivalent,equivalent,nonequivalent}weak_ordering与值{ less,equivalent,greater}隐式转换为:
partial_ordering用值{ less,equivalent,greater}weak_equality用值{ nonequivalent,equivalent,nonequivalent}partial_ordering与值{ less,equivalent,greater,unordered}隐式转换为:
weak_equality用值{ nonequivalent,equivalent,nonequivalent,nonequivalent}strong_equality值{ equal,unequal}隐式转换为:
weak_equality值{ equivalent,nonequivalent}该<=>令牌介绍.旧源代码中的字符序列<=>标记为<= >.例如,X<&Y::operator<=>需要添加一个空格来保留其含义.
可重载运算符<=>是一种三向比较函数,其优先级高于<和低于<<.它返回一个可以与文字进行比较的类型,0但允许其他返回类型,例如支持表达式模板.<=>在语言和标准库中定义的所有运算符都返回上述5 std::种比较类别类型中的一种.
对于语言类型,提供了以下内置的<=>相同类型比较.除非另有说明,否则所有都是constexpr.使用标量促销/转换不能异步调用这些比较.
bool,整数和指针类型,<=>返回strong_ordering. <=>,并且内置异构operator<=>(T*, nullptr_t).只有指向同一对象/分配的指针的比较才是常量表达式.<=>返回partial_ordering,并且可以通过将参数扩展为更大的浮点类型来异步调用.<=>返回与枚举的基础类型相同<=>.nullptr_t,<=>回报strong_ordering和总是收益equal.T[N] <=> T[N]返回与Ts 相同的类型<=>并执行字典元素比较.<=>其他阵列没有.void没有<=>.为了更好地理解该操作员的内部工作原理,请阅读原始论文.这正是我发现使用搜索引擎的原因.
小智 23
C++ 20 中引入了三向比较运算符 (<=>)。
该表达式返回如下对象;
auto cmp = a <=> b;
cmp > 0 if a > b
cmp = 0 if a == b
cmp < 0 if a < b
Run Code Online (Sandbox Code Playgroud)
示例程序
#include <iostream>
using namespace std;
int main()
{
int lhs = 10, rhs = 20;
auto result = lhs <=> rhs;
if (result < 0) {
cout << "lhs is less than rhs" << endl;
}
else if (result > 0) {
cout << "lhs is greater than rhs" << endl;
}
else {
cout << "lhs and rhs are equal" << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
如何编译并运行?
g++-10 threewaycmp.cpp -std=c++20
./a.out
Run Code Online (Sandbox Code Playgroud)
结果
lhs is less than rhs
Run Code Online (Sandbox Code Playgroud)
请参阅以下链接了解更多详细信息 https://en.cppreference.com/w/cpp/language/operator_comparison
Sti*_*mer 11
由于引用的网页已更改,因此此答案变得无关紧要
您引用的网页已损坏.那天正在编辑很多,不同的部分不同步.我在看它时的状态是:
在页面顶部,它列出了当前存在的比较运算符(在C++ 14中).没有<=>.
在页面的底部,他们应该列出相同的运营商,但他们蠢蠢欲动,并添加了这个未来的建议.
gcc还不知道<=>(并且-std=c++14,从不会),所以它认为你的意思a <= > b.这是解释错误消息.
如果你从现在起五年后尝试同样的事情,你可能会收到更好的错误信息,例如 <=> not part of C++14.
默认<=>自动==, !=, <, >, <=, >=免费提供
C++20 有一个新的“默认比较”功能设置,因此默认设置<=>免费提供所有其他功能。我相信这是添加operator<=>.
改编自https://en.cppreference.com/w/cpp/language/default_comparisons:
主程序
#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));
}
Run Code Online (Sandbox Code Playgroud)
编译并运行:
sudo apt install g++-10
g++-10 -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Run Code Online (Sandbox Code Playgroud)
上面的一个等效的更明确的版本是:
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;
};
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们需要显式设置,bool operator==(const Point& other) const = default;因为如果operator<=>没有默认(例如上面明确给出),则operator==不会自动默认:
每对任何规则的
operator<=>过载,一个默认的<=>超载也将允许类型进行比较了<,<=,>,和>=。如果
operator<=>是默认值并且operator==根本没有声明,则operator==隐式默认值。
上面的示例使用与 default 相同的算法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));
}
Run Code Online (Sandbox Code Playgroud)
有错误:
main.cpp:16:18: error: no match for ‘operator!=’ (operand types are ‘Point’ and ‘Point’)
16 | assert( (pt1 != pt2));
| ~~~ ^~ ~~~
| | |
| Point Point
Run Code Online (Sandbox Code Playgroud)
然而,上面确实可以编译-std=c++20。
在 Ubuntu 20.04、GCC 10.2.0 上测试。
| 归档时间: |
|
| 查看次数: |
26756 次 |
| 最近记录: |