I created a class in C++ with an implementation for operator<=> and operator==. Their logic is different: operator<=> compares based on one field, and operator== compares based on another field. I added a Student to a set, then called find on that set with a Student that wasn't in the set.
#include <iostream>
#include <set>
#include <string>
using namespace std;
class Student {
private:
string name;
int age;
public:
Student (string p_name, int p_age) : name {p_name}, age {p_age} {};
// Students are ordered in respect to their age
auto operator<=>(const Student& rhs) const {
return age <=> rhs.age;
}
// A student is equal to another if they have the same name
bool operator==(const Student& rhs) const {
return name == rhs.name;
}
};
int main() {
Student john {"john", 10};
Student lucas {"lucas", 10};
set<Student> my_set;
my_set.insert(john);
std::cout << std::boolalpha;
std::cout << "Does my_set contain lucas? " << my_set.contains(lucas) << std::endl;
}
I want my_set.contains(lucas) to return false, instead, it returns true.
Operators are just function calls; you can have them do anything you want, within the limitations of the language. It is within your rights to make your code as incoherent as you like.
However, once you give such incoherent code to some other code (like, say, the standard library), you are now at the mercy of that other code's expectations. And those expectations tend to be "things do what they say they do".
It is therefore always best to make operators do what they are supposed to do. If for some values
aandbsuch thatoperator<=>(a, b) != 0, thenoperator==(a, b) == falsetoo. That will be the expectation of pretty much any code not under your control which intends to use either of these operators.std::set<T>is an associative, ordered container; this means that it puts theTitems in an order and maintains this order automatically as items are added or removed. The ordering is defined by a comparison object given to the template, which defaults tostd::less<T>(aka: useoperator<). Sinceoperator<is based onoperator<=>, that is what is used to define comparisons.All comparisons. Two values
aandbare equal whencomp(a, b) == comp(b, a). Sincecomphere isstd::less<T>, it will always useoperator<to determine equality. That is, two objects are equal if neither is less than the other.You cannot make
std::setuseoperator==for this (it only takes one comparison function). Nor wouldsetwork if you did, since the internal structure of the type presumes that equivalence is based on the comparison function's ordering. That is, the reason whyset::findis O(log(n)) is because all of the objects are put into an order based on the comparison function.So not only is what you want just bad code, it is code that could never work with any associative container. If you want to write incoherent code, you can, but the consequences of writing incoherent code are that the rest of the world expands and demands coherence.