<=>
运算符是做什么用的?自2017年以来,cppreference.com更新了该页面,现在包含了关于
<=>
运算符的详细信息。<=>
运算符是做什么用的?<=>
运算符的详细信息。这被称为三路比较运算符。
根据P0515文件提案:
有一个新的三路比较运算符,
<=>
。表达式a <=> b
返回一个对象,如果a < b
,则比较结果为<0
,如果a > b
,则比较结果为>0
,如果a
和b
相等/等价,则比较结果为==0
。要为类型编写所有比较,请只需编写返回适当类别类型的
operator<=>
:
如果您的类型自然支持
<
,则返回_ordering,我们将高效生成<
、>
、<=
、>=
、==
和!=
;否则返回_equality,我们将高效生成==和!=。如果对于您的类型,
a == b
意味着f(a) == f(b)
(可替换性,其中f仅读取使用非私有const接口访问的比较相关状态),则返回strong;否则返回weak。
三路比较运算符表达式的形式为:
lhs <=> rhs (1)
该表达式返回一个对象,
- 如果
lhs < rhs
,则比较结果为<0
- 如果
lhs > rhs
,则比较结果为>0
- 如果
lhs
和rhs
相等或等效,则比较结果为==0
<0>
”,“compares >0
”和“compares ==0
”是什么意思,它们意味着<=>
根据参数返回负数、正数或零值。就像strncmp
和memcmp
一样。 - Cornstalks'a' < 'a'
和 'c' < 'a'
都是 false,但是 'a' < 'a'
和 'a' < 'c'
不是。在强排序中,以下语句成立:a != b
→ a < b || b < a
。 - Revolver_Ocelotoperator==(T x, T y) { return !(x < y) && !(y < x); }
和 operator!=(T x, T y) { return (x < y) || (y < x); }
- 啊哈!当然这比真正的 ==
不太高效,因为它会两次调用比较,但仍然很不错。 - Dai< 0
进行比较时,它会返回。也就是说,如果 a < b
,那么 (a <=> b) < 0
总是为真。 - rmobisauto X::operator<=>(const Y&) =default;
比较类别 |
---|
定义了五个比较类别,分别为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 │ │
└──────────────────┴──────┴────────────┴───────────────┴─────────────┘
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的。这些比较不能使用标量提升/转换进行异构调用。_equality
类型已经废弃:事实证明 <=>
与四个关系运算符配合得很好,但与两个相等运算符配合得不太好(尽管有一些强大的语法糖支持常见情况下同时使用所有运算符)。 - Davis Herring<=>
操作符会自动获得==, !=, <, >, <=, >=
操作符的功能。<=>
操作符会自动获得其他所有操作符的功能。我相信这是添加operator<=>
的主要动机。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 (auto cmp = x <=> other.x; cmp != 0)
return cmp;
return y <=> other.y;
}
bool operator==(const Point& other) const = default;
};
bool operator==(const Point& other) const = default;
,因为如果operator<=>
没有默认值(例如上面明确给出的情况),那么operator==
就不会自动默认:operator<=>
重载的规则,一个默认的<=>
重载也将允许使用<
,<=
,>
和>=
来比较类型。operator<=>
被默认化且根本没有声明operator==
,那么operator==
将被隐式默认化。operator<=>
相同的算法,如cppreference所解释的那样:#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
当我们进行了实现时:
auto operator<=>(const Point& other) const {
if (auto cmp = x <=> other.x; cmp != 0)
return cmp;
return y <=> other.y;
}
auto
会给我们返回std::strong_ordering
,因为这是<=>
在两个整数之间返回的结果,正如在https://en.cppreference.com/w/cpp/language/operator_comparison中提到的。
否则,如果操作数具有整数类型,则该运算符产生一个类型为std::strong_ordering的prvalue。
这就是我们对整数点所期望的语义。
当在浮点数之间使用<=>
时,会得到partial_ordering
,因为存在"不可比较"的NaN
的可能性。
TODO 具体的weak_ordering
和partial_ordering
的示例。
Practical meaning of std::strong_ordering and std::weak_ordering表明,在标准库中目前没有它们产生不同结果的示例。
相关:PartialOrdering, StrictWeakOrdering, TotalOrdering, 在应用中的主要区别是什么 在Ubuntu 20.04、GCC 10.2.0上进行了测试。<=>
时,它是否应该同时给出 ==
? 对我来说,它会重载 >
和 <
,但是会提示缺少 ==
运算符... 使用默认设置时就没有问题。 - Tonybool operator==(const Point& other) const = default;
。 - Ciro Santilli OurBigBook.com<=>
应该返回一些比较类别(在您的例子中,std::strong_ordering
是有意义的)。如果将其返回类型设为 int
,则无法进行组合。 - undefined。
std::common_comparison_category在
int`上不起作用。 - undefinedC++ 20引入了三路比较运算符(<=>)。
该表达式返回以下对象;
auto cmp = a <=> b;
cmp > 0 if a > b
cmp = 0 if a == b
cmp < 0 if a < b
示例程序
#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;
}
}
如何编译和运行?
g++-10 threewaycmp.cpp -std=c++20
./a.out
结果
lhs is less than rhs
请参考以下链接以获取更多详细信息:
https://en.cppreference.com/w/cpp/language/operator_comparison由于引用的网页已更改,此答案已失效
您所引用的网页已经失效。当时正在对该网页进行编辑,不同部分之间没有同步。 我查看时的状态如下:
在页面顶部,它列出了当前存在的比较运算符(在C++14中)。那里没有<=>
。
在页面底部,它们应该列出相同的运算符,但出现了未来的建议。
gcc
目前还不知道<=>
(使用-std=c++14
, 将永远不会有),所以它认为你意思是 a <= > b
。这解释了错误消息的原因。
如果你五年后尝试同样的事情,你可能会得到更好的错误信息,比如<=>不是C++14的一部分。
<=>
运算符,告诉你可以期望在哪个版本的标准中找到它。标准标签是cppreference.com遵循的惯例。当然,你没有一个时光机器回来支持它的编译器,但cpprefernce会(正确地)告诉你可以期望什么。 - Spencer<=>
运算符是什么?”它更适合作为对问题的评论。 - undefined<=>
的优点在于对于比较昂贵的复杂类型,例如树形导航等情况。您可以执行一次 int x = A <=> B;
,然后从 x
确定 >
、<
、>=
、<=
、==
、!=
,而无需进行 A 和 B 的其他比较。对于树形结构,想象一下 bool find(root, A){ if root is nullptr return false; int x = A <=> root->B; if !x, you found it return true, else if x < 0, find left, else find right}。(调整尾递归。)
我认为某些语言具有三路控制流,例如 switch,但很难通过 Google 回忆起来。这是一个涉及 C strcmp()、memcmp(),并继续使用 JAVA compareTo() 的情况。请帮我众包!
bar< foo::operator<=>
是一个示例,说明它可能像<--
运算符一样。 - Yakk - Adam Nevraumont