C++ ordering

02 Sep 2013

When writing your own classes in C++ code you often need to implement the operator< member function. This function is used by all stl containers that rely on ordering such as std::set and std::map. Through my years of programming I have seen multiple ways of creating these ordering functions and there are some ways I like and some that I dislike. I will show an example of these implementation in this note.

To start off lets create a small class which we need to put into an std::set. So we need to define the class and it's member variables.

class Box {
    int width
    int height
    int depth

Now when we put this into an ordered container we also need the operator< member function so i will create one that is comonly created in C++ code.

bool operator<(Box a, Box b) {
    return a.width < b.width || 
        (a.width == b.width && a.height < b.height) || 
        (a.width == b.width && a.height == b.height && a.depth < b.depth);

This function works and in many codebases this is the ideomatic way of creating a less than function. The problem with this approach is that it can be a bit hard to reason about because of all the nested logical operators. When you have to break a oneliner into multiple lines and add parentheses to make it more readable and correct you should start to smell the code fart. Another problem is that each time you add a new member variable to the class your operator< function will increase significantly in size.

So I propose another solution to the ordering function which does not have these problems.

bool operator<(Box a, Box b) {
    if (a.width != b.width)
        return a.width < b.width;
    if (a.height != b.height)
        return a.height < b.height;
    return a.depth < b.depth;

In this implementation it is easier to reason about the code because each step only operates on a single variable. And if you add more fields to the class it is quite trivial to add an additional check to this function. I call this the "less than function that does not suck pattern".