https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100330
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Reduced:
#include <utility>
extern "C" int puts(const char*);
struct vertex_descriptor {
operator bool() const {
puts(__func__);
return i;
}
bool operator<(const vertex_descriptor b) const {
puts(__func__);
return i < b.i;
}
int i = 0;
};
int main()
{
std::pair<vertex_descriptor, int> p1({1}, 0);
std::pair<vertex_descriptor, int> p2({2}, 0);
if (!(p1 < p2))
throw 1;
}
This aborts in C++20. I think GCC is correct according to the standard.
In C++20 the operator< for std:pair<T,U> is synthesized from operator<=>.
That uses the synth-three-way helper defined in
http://wg21.link/expos.only.func which determines that vertex_descriptor is
three-way-comparable, and so uses <=> to compare them. But that uses your
implicit conversion to bool, i.e. it is equivalent to p1.first==true <=>
p2.first==true
An explicit operator bool avoids the problem, because synth-three-way will not
implicitly convert the operands to bool, and so will do:
if (p1.first < p2.first) return weak_ordering::less;
if (p2.first < p1.first) return weak_ordering::greater;
return weak_ordering::equivalent;
This uses vertex_descrioptor::operator< as intended.