LibraryThree-Way Comparison

Three-Way Comparison

Learn about Three-Way Comparison as part of C++ Modern Systems Programming and Performance

C++ Three-Way Comparison: Enhancing Code Readability and Performance

In modern C++, the introduction of the three-way comparison operator (

code
<=>
), often called the 'spaceship operator', significantly simplifies the way we define comparison logic for our classes and structs. This operator allows us to define all six relational comparison operators (
code
<
,
code
<=
,
code
>
,
code
>=
,
code
==
,
code
!=
) with a single definition, leading to more concise, readable, and less error-prone code. It's a cornerstone of modern C++ for creating robust and efficient data structures.

Understanding the Three-Way Comparison Operator (`<=>`)

The three-way comparison operator compares two operands and returns an object that indicates their ordering. This returned object is typically of an enumeration type, such as

code
std::strong_ordering
,
code
std::weak_ordering
, or
code
std::partial_ordering
, defined in the
code
header. These types clearly signal the nature of the comparison: strong (no equality without identity), weak (equality without identity), or partial (not all elements are comparable).

The spaceship operator (`<=>`) generates all six comparison operators from a single definition.

Instead of writing separate functions for <, <=, >, >=, ==, and !=, you can define just one operator<=>. The compiler then automatically synthesizes the rest.

When you define operator<=>(const MyClass& other) const, the compiler can deduce the implementations for operator<(const MyClass& other) const, operator<=(const MyClass& other) const, operator>(const MyClass& other) const, operator>=(const MyClass& other) const, and operator==(const MyClass& other) const. This is a powerful feature for reducing boilerplate code and ensuring consistency in comparison logic.

Return Types of Three-Way Comparison

The return type of

code
operator<=>
is crucial as it dictates the semantics of the comparison. The standard library provides three distinct types for this purpose:

Return TypeMeaningExample Use Case
std::strong_orderingIndicates a total ordering where equality implies identity. If a <=> b is equal, then a and b are considered the same.Comparing integers, strings, or objects where equality means the objects are identical.
std::weak_orderingIndicates an ordering where equality does not imply identity. For example, two different objects might compare as equal if they represent the same value.Comparing floating-point numbers where NaN might compare equal to itself, or comparing objects based on a specific field that might have duplicates.
std::partial_orderingIndicates that not all elements are necessarily comparable. Some pairs might return unordered.Comparing floating-point numbers where NaN is not comparable to anything, including itself.

Automatic Generation of Comparison Operators

When you define

code
operator<=>
for a class, the compiler can automatically generate the other comparison operators. This is particularly useful when your class members themselves support three-way comparison. The compiler will generate the missing operators based on the result of your
code
operator<=>
definition.

What is the primary benefit of using the three-way comparison operator (<=>) in C++?

It allows defining all six relational comparison operators with a single definition, leading to more concise, readable, and less error-prone code.

Consider a simple

code
Point
struct. By defining
code
operator<=>
, we automatically get all other comparison operators.

Consider a Point struct with x and y coordinates. When we define operator<=>(const Point& other) const, the compiler first compares x coordinates. If they are equal, it then compares y coordinates. The result of the y comparison is returned. This logic can be expressed as:

struct Point {
    int x, y;

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

This default implementation automatically generates the comparison logic based on the members' own comparison operators.

📚

Text-based content

Library pages focus on text content

Performance Implications

Using

code
operator<=>
with the
code
default
keyword can lead to performance improvements. The compiler can often generate more efficient code than manually written comparison functions, especially when dealing with complex data structures. It avoids redundant comparisons and can leverage specific optimizations for the underlying types.

The default keyword for operator<=> is a powerful tool for generating efficient and correct comparison logic with minimal code.

When to Use `operator<=>`

You should consider using

code
operator<=>
whenever you need to define ordering for your custom types, especially when you want to leverage the automatic generation of other comparison operators. This is common in scenarios like:

  • Defining comparison for elements in containers (e.g.,
    code
    std::vector
    ,
    code
    std::map
    ).
  • Implementing sorting algorithms.
  • Creating data structures that require ordering semantics.
What are the three standard return types for C++ three-way comparison operators, and what do they signify?

std::strong_ordering (equality implies identity), std::weak_ordering (equality doesn't imply identity), and std::partial_ordering (not all elements are comparable).

Learning Resources

C++ Core Guidelines: Operator Overloading(documentation)

Provides authoritative guidance on operator overloading, including the use of the three-way comparison operator.

cppreference.com: Three-way comparison(documentation)

A comprehensive reference detailing the syntax, semantics, and return types of the three-way comparison operator.

C++20: The Three-Way Comparison Operator (<=>)(blog)

An in-depth blog post explaining the spaceship operator with practical examples and its benefits.

Understanding C++20's Three-Way Comparison Operator(blog)

Explores the nuances of the three-way comparison operator, including its default implementation and return types.

C++20: The Spaceship Operator (<=>)(blog)

A clear explanation of the spaceship operator, its usage, and how it simplifies comparison logic in C++.

C++20 Three-Way Comparison - Scott Meyers(video)

A video presentation by Scott Meyers discussing the three-way comparison operator and its impact on C++ development.

C++20: Defaulted Comparison Operators(video)

A video tutorial demonstrating how to use the `default` keyword with comparison operators in C++20.

The `<compare>` Header in C++20(paper)

While not exclusively about `<=>`, this paper touches upon comparison concepts and their formalization in C++.

C++ Standard Library - `<compare>`(documentation)

Official documentation for the `<compare>` header, which defines the ordering types used with three-way comparison.

Three-way comparison - Wikipedia(wikipedia)

A general overview of the concept of three-way comparison in computer science, providing context for its use in C++.