为自定义类重载
operator bool()
T
会破坏 vector<T>
比较运算符。
以下代码在第一个在线编译器上尝试过,谷歌建议我打印
v1 > v2: 0
v1 < v2: 1
当
operator bool()
被评论并且
v1 > v2: 0
v1 < v2: 0
当它未被注释时。
#include <iostream>
#include <vector>
class T {
int _value;
public:
constexpr T(int value) : _value(value) {}
constexpr bool operator==(const T rhs) const { return _value == rhs._value; }
constexpr bool operator!=(const T rhs) const { return _value != rhs._value; }
constexpr bool operator <(const T rhs) const { return _value < rhs._value; }
constexpr bool operator >(const T rhs) const { return _value > rhs._value; }
//constexpr operator bool() const { return _value; } // <-- breaks comparison
};
int main()
{
auto v1 = std::vector<T>{1,2,3};
auto v2 = std::vector<T>{1,2,9};
std::cout << "v1 > v2: " << (v1 > v2) << std::endl;
std::cout << "v1 < v2: " << (v1 < v2) << std::endl;
return 0;
}
仅从 C++20 开始这似乎是正确的。
std::vector
下面发生了什么变化?
从我的角度来看,这非常可怕。
C++20 将
<
(以及许多其他标准类)的各个 <=
、>
、>=
、std::vector
运算符替换为单个 <=>
。
在内部,它尝试使用
<=>
来比较元素,如果类型没有重载 <=>
,则回退到旧的运算符。
由于您有一个非显式
operator bool
,因此应用 <=>
会将两个操作数转换为 bool 并比较它们。解决方法是使 operator bool
explicit
(这通常是一个好主意)(这样 <=>
会失败并且 vector
会退回到旧的运算符),和/或替换 <
、<=
,>
,>=
与 <=>
(总的来说这也是一个好主意)。