Overloading the operator bool()
for a custom class T
breaks std::vector<T>
comparison operators.
The following code tried on the first online compiler google suggest me prints
v1 > v2: 0
v1 < v2: 1
when operator bool()
is commented and
v1 > v2: 0
v1 < v2: 0
when it's uncommented.
#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;
}
This appears to be true only starting from C++20. What's changed underneath in std::vector
?
C++20 replaces the individual <
,<=
,>
,>=
operators of std::vector
(and of many other standard classes) with a single <=>
.
Internally it tries to use <=>
to compare the elements, and falls back to the old operators if the type doesn't overload <=>
.
Since you have a non-explicit operator bool
, applying <=>
converts both operands to bool and compares those. The fix is to make operator bool
explicit
(which is a good idea in general) (so that <=>
fails and vector
falls back to the old operators), and/or replace <
,<=
,>
,>=
with <=>
(which is also a good idea in general).