Why is equality needed for rel_ops? Isn't "<" enough?
a==b => !(a<b) && !(b<a)
It might be a very stupid question. Am I missing something?
Why is equality needed for rel_ops? Isn't "<" enough?
a==b => !(a<b) && !(b<a)
It might be a very stupid question. Am I missing something?
Why is equality needed for rel_ops? Isn't "<" enough?
a==b => !(a<b) && !(b<a)
Because this is not true in general. If rel_ops would work only for relational operators that follow that logic it would be rather limited.
I guess what you have in mind is the weak ordering required for the < operator for associative containers. From cppreference:
Everywhere the standard library uses the Compare requirements, uniqueness is determined by using the equivalence relation. In imprecise terms, two objects a and b are considered equivalent (not unique) if neither compares less than the other: !comp(a, b) && !comp(b, a).
In simple terms: Whether two keys are considered the "same" is only determined by requiring ! (a < b) && ! (b < a). Hence you only need to supply a < for associative containers and no operator== to decide whether two keys are the same. However, equivalence (!(a<b)&&!(b<a)) is not necessarily the same as equality (a==b).
For example when you use this
struct my_key {
int a;
int b;
bool operator< (const key_type& other) {
return a < other.a; // not comparing b !
}
};
as a key of a std::map then my_key{1,0} and my_key{1,2} are equivalent ("same key"), even though they are not equal. As another example, consider a Point in spherical coordinates where we choose to have a < b when a is closer to the origin than b:
struct Point {
double radius;
double angle;
bool operator<(const Point& other) {
return radius < other.radius;
}
bool operator==(const Point& other) {
return (radius == other.radius) && (angle == other.angle);
}
}
Also here all three a < b,b < a and a == b can be false at the same time.
Also note that (from cppreference)
As of C++20, std::rel_ops are deprecated in favor of operator<=>.
For the starship operator <=> you can choose between
std::strong_ordering
std::weak_ordering
std::partial_ordering
std::strong_equality
std::weak_equality
Weak ordering is what is required eg for std::map (eg my_key or Point), while for strong ordering equivalence and equality are basically the same. For more details and examples I refer you to this.
Yes, actually you are missing sth. And it is very fundamental. It is not about C++ or programing. It's about math. According to math, your statement is true if and only if "<" defines a strict weak ordering on its operand domain. Not every user-defined type with "less" rel_op has a weak ordering.