# C++ Named Requirements: Compare

## Introduction

Given two values $a$ and $b$, by *comparing* their values, there could be one of the three *ordering* relationships between them, equal, i.e., the order of $a$ and $b$ cannot be determined from their values, $a$ strictly appears before $b$, and $b$ strictly appears before $a$. It appears that we would have to define two functions, $\text{equal}(x, y)$ which tells us whether $x$ is equal to $y$ and $\text{comp}(x, y)$ which tells us whether $x$ strictly appears before $y$, in order to explicitly determine which of the three ordering relationship the two values $a$ and $b$ belong to.

Close examination reveals that we can define $\text{equal}(x, y)$ using $\text{comp}(x, y)$ and boolean relationships $\text{and}$ and $\text{not}$, since the three ordering relationships are mutually exclusive. Concretely,

$$

\text{equal}(x, y) \triangleq \left(\text{not} \ \text{comp}\left(x, y\right)\right) \ \text{and} \ \left(\text{not} \ \text{comp}\left(y, x\right)\right)

$$

In fact, in C++ STL, most containers take one single *compare* function that can be used for determining the ordering relationship. In this blog post, I would like to quickly discuss about the caveats of compare functions in C++.

## Caveats

The compare in C++ really means whether the first argument of the call appears before the second in the **strict** weak ordering relation induced by this type.

Many C++ STL containers are ordered containers, such as `std::set`

, `std::map`

, `std::multiset`

, `std::multimap`

. They take one compare function in the constructors. For example, the default compare function is `std::less`

, which means by default, when we iterate from the beginning to the end of the sequence, the values in the sequence are in ascending order.

Now, what if we want to reverse the order of the values in the sequence? In our case, we want to have a descending-ordered sequence for those STL containers. Should we use `std::greater_equal`

for the compare function in the constructor? The answer is no. `std::greater_equal`

is not a *compare* function, because it does not follow the strict weak ordering relationship property. The consequence of using non-compare functions for ordered STL containers is that determining whether the two values are equal will not work as expected. For example, testing equivalence in the STL container using `std::greater_equal`

will be

$$

\begin{align}

\text{equal}(8, 8) &= \left(\text{not} \ \text{geq}\left(8, 8\right)\right) \ \text{and} \ \left(\text{not} \ \text{geq}\left(8, 8\right)\right) \\

&= \left(\text{not} \ \text{true} \right) \ \text{and} \ \left(\text{not} \ \text{true} \right) \\

&= \text{false} \ \text{and} \ \text{false} \\

&= \text{false} \\

\end{align}

$$

which is incorrect.

The correct compare function to use to reverse the order of the values in the sequence will be using `std::greater`

instead of `std::greater_equal`

.

## Conclusions

Always have *compare* functions return false for equal values.

## References

C++ Named Requirements: Compare