三向比较运算符与减法有何不同?
How is the three-way comparison operator different from subtraction?
C++20 中有一个新的比较运算符 <=>
。但是我认为在大多数情况下,简单的减法效果很好:
int my_strcmp(const char *a, const char *b) {
while (*a == *b && *a != 0 && *b != 0) {
a++, b++;
}
// Version 1
return *a - *b;
// Version 2
return *a <=> *b;
// Version 3
return ((*a > *b) - (*a < *b));
}
它们的作用是一样的。我真的无法理解其中的区别。
以下是减法不起作用的一些情况:
unsigned
种。
- 导致整数溢出的操作数。
- 未定义
operator -
的用户定义类型(可能是因为它没有意义 - 可以在不定义距离概念的情况下定义顺序)。
我怀疑这份清单并不详尽。
当然,至少可以针对#1 和#2 提出解决方法。但是 operator <=>
的目的是封装这种丑陋。
该运算符解决了减法时出现的数值溢出问题:如果从接近 INT_MIN
的负数中减去一个较大的正数,您将得到一个无法表示为 int
,从而导致未定义的行为。
虽然版本 3 没有这个问题,但它完全缺乏可读性:以前从未见过这个技巧的人需要一些时间才能理解。 <=>
运算符也修复了可读性问题。
这只是新运营商解决的一个问题。 Herb Sutter's Consistent comparison paper 的第 2.2.3 节讨论了 <=>
与语言的其他数据类型的使用,其中减法可能会产生不一致的结果。
这里有一些关于差异的有意义的答案,但是 his paper 中的 Herb Sutter 特别指出:
<=> is for type implementers: User code (including generic code) outside the implementation of an operator<=> should almost never invoke an <=> directly (as already discovered as a good practice in other languages);
所以即使没有区别,运算符的意义也不同:帮助 class 作者生成比较运算符。
减法运算符和 "spaceship" 运算符的核心区别(根据 Sutter 的提议)是重载 operator-
给你一个减法运算符,而重载 operator<=>
:
- 给你6个核心比较运算符(即使你把运算符声明为
default
:没有代码可写!);
- 声明你的class是否具有可比性,是否可排序,以及顺序是全部还是部分(strong/weak在Sutter的提案中);
- 允许异构比较:您可以重载它以将您的 class 与任何其他类型进行比较。
其他区别在于 return 值:operator<=>
会 return 一个 class 的 enum
,class 指定是否类型是可排序的,排序是强还是弱。 return 值将转换为 -1、0 或 1(尽管 Sutter 为 return 类型留出了空间以指示距离,就像 strcmp
那样)。无论如何,假设 -1, 0, 1 return 值,我们最终会得到 a true signum function in C++! (signum(x) == x<=>0
)
C++20 中有一个新的比较运算符 <=>
。但是我认为在大多数情况下,简单的减法效果很好:
int my_strcmp(const char *a, const char *b) {
while (*a == *b && *a != 0 && *b != 0) {
a++, b++;
}
// Version 1
return *a - *b;
// Version 2
return *a <=> *b;
// Version 3
return ((*a > *b) - (*a < *b));
}
它们的作用是一样的。我真的无法理解其中的区别。
以下是减法不起作用的一些情况:
unsigned
种。- 导致整数溢出的操作数。
- 未定义
operator -
的用户定义类型(可能是因为它没有意义 - 可以在不定义距离概念的情况下定义顺序)。
我怀疑这份清单并不详尽。
当然,至少可以针对#1 和#2 提出解决方法。但是 operator <=>
的目的是封装这种丑陋。
该运算符解决了减法时出现的数值溢出问题:如果从接近 INT_MIN
的负数中减去一个较大的正数,您将得到一个无法表示为 int
,从而导致未定义的行为。
虽然版本 3 没有这个问题,但它完全缺乏可读性:以前从未见过这个技巧的人需要一些时间才能理解。 <=>
运算符也修复了可读性问题。
这只是新运营商解决的一个问题。 Herb Sutter's Consistent comparison paper 的第 2.2.3 节讨论了 <=>
与语言的其他数据类型的使用,其中减法可能会产生不一致的结果。
这里有一些关于差异的有意义的答案,但是 his paper 中的 Herb Sutter 特别指出:
<=> is for type implementers: User code (including generic code) outside the implementation of an operator<=> should almost never invoke an <=> directly (as already discovered as a good practice in other languages);
所以即使没有区别,运算符的意义也不同:帮助 class 作者生成比较运算符。
减法运算符和 "spaceship" 运算符的核心区别(根据 Sutter 的提议)是重载 operator-
给你一个减法运算符,而重载 operator<=>
:
- 给你6个核心比较运算符(即使你把运算符声明为
default
:没有代码可写!); - 声明你的class是否具有可比性,是否可排序,以及顺序是全部还是部分(strong/weak在Sutter的提案中);
- 允许异构比较:您可以重载它以将您的 class 与任何其他类型进行比较。
其他区别在于 return 值:operator<=>
会 return 一个 class 的 enum
,class 指定是否类型是可排序的,排序是强还是弱。 return 值将转换为 -1、0 或 1(尽管 Sutter 为 return 类型留出了空间以指示距离,就像 strcmp
那样)。无论如何,假设 -1, 0, 1 return 值,我们最终会得到 a true signum function in C++! (signum(x) == x<=>0
)