Most C++ STL algorithms API impose certain requirements on comparator functions like transitivity (see Cppreference for details). The requirements are intuitively understandable except for the transitivity of equivalence (aka transitivity of incomparability):
- if
aandbare equivalent (i.e.!(a < b) && !(b < a)) andbandcare equivalent (i.e.!(b < c) && !(c < b)) thenaandcmust be equivalent as well.
What is the intuition behind this requirement?
For the mathematically inclined: I do understand that transitivity of equivalence allows us to define a strict total order over equivalence classes but this does not add much to understanding...
If you drop the requirement, then you are only requiring a partial order.
This immediately has two issues that come to mind:
Incomparability is not an equivalence relation any more, so e.g. containers like
std::setcan't use it to determine equivalence of keys any more. This could of course be worked around by having them take an explicit equivalence relation as additional parameter as e.g.std::unordered_setdoes.Finding a total order that extends a partial order is not possible efficiently. Suppose that in a set of
Nobjects, all are incomparable except for object A and object B. You need to test worse case all pairs of elements in order to figure out thatAandBneed a particular order because incomparability of any two elements doesn't imply anything any more about comparison with other elements. So something likestd::sortcould not be specified to haveN*log(N)worse case complexity. I also expect that it would generally make it impossible to implementO(log(N))operations required for e.g.std::set/std::map.