Skip to Content
Course content

37: Operator Overloading: Comparison Operators

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I was working on a small plugin manager the other day and realized I needed a way to check if a user's installed version of a library was compatible with a required version. Naturally, I built a Version struct to hold the major, minor, and patch numbers. It seemed simple enough.

struct Version {
    int major;
    int minor;
    int patch;
};

Version v1{1, 2, 0};
Version v2{1, 2, 1};

if (v1 == v2) { 
    // Do something
}

The compiler's lack of intuition

When I tried to compile that, the compiler immediately complained. It had no idea what == meant when applied to two Version objects. To us, it's obvious: "just check if all the numbers match." To C++, a struct is just a blob of memory. It doesn't assume you want a member-wise comparison.

So, I need to tell C++ how to handle this. I'll overload the == operator. I'll make it a const member function because comparing two versions shouldn't change the versions themselves.

struct Version {
    int major, minor, patch;

    bool operator==(const Version& other) const {
        return major == other.major && 
               minor == other.minor && 
               patch == other.patch;
    }
};

Now v1 == v2 works. But here's where things get tedious. In a versioning system, I don't just need to know if they are equal; I need to know if one is older than the other so I can trigger an update. I tried if (v1 < v2), and—surprise—another compiler error.

The logic of "Less Than"

Implementing operator< is trickier than equality. I can't just check if major < other.major && minor < other.minor... because if the major version is higher, the minor version doesn't even matter. 1.0.0 is always newer than 0.9.9, regardless of that 9.

I'll try to write this out logically: check the major version first. If they're different, that's my answer. If they're the same, move to the minor. If those are the same, move to the patch. It looks like this:

bool operator<(const Version& other) const {
    if (major != other.major) return major < other.major;
    if (minor != other.minor) return minor < other.minor;
    return patch < other.patch;
}

This works, but I'm already feeling the friction. If I want to support >, <=, and >=, am I really going to write five different functions that all do essentially the same comparison logic? That's a recipe for a typo and a nightmare to maintain.

The "Spaceship" Shortcut

If you're using C++20 or newer, there is a much more elegant way to handle this. There's a new operator called the three-way comparison operator, or the "spaceship operator" (<=>) because of how it looks. Instead of returning a boolean, it returns a value that tells you if the left side is less than, equal to, or greater than the right side.

The real magic happens when you use = default. Let's see what happens if I replace all my manual comparison operators with this:

#include <compare>

struct Version {
    int major, minor, patch;

    auto operator<=>(const Version& other) const = default;
};

By defaulting the spaceship operator, C++ automatically generates ==, !=, <, >, <=, and >= for me. It does exactly what I did manually: it compares the members in the order they are declared in the struct. Since I declared major, then minor, then patch, the lexicographical comparison happens automatically.

I've spent years writing those tedious if (a != b) return a < b; blocks. Using <=> is a massive quality-of-life improvement. Just remember that if you need a custom comparison logic—like if a certain version flag overrides everything else—you'll have to write the <=> logic yourself instead of defaulting it.




📋 Practical Task

Implementing a Coordinate Distance Comparison

You are building a 2D game engine. You have a Point struct with x and y coordinates. You want to be able to compare two Point objects based on their distance from the origin (0,0). A point is considered "less than" another point if it is closer to the origin.

Your Task:

  • Create a Point struct with double x and double y.
  • Overload the == operator to check if two points are at the exact same coordinates.
  • Overload the < operator to compare their distance from the origin using the formula: $\sqrt{x^2 + y^2}$. (Note: For optimization, you can compare $x^2 + y^2$ instead of taking the square root).
  • Write a main function that creates three points: p1{1.0, 1.0}, p2{0.0, 2.0}, and p3{5.0, 5.0}.
  • Print whether p1 < p2 and whether p1 == p2.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.