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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With