> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Three-Way Comparison

The `<=>` operator, formally known as the three-way comparison operator (and colloquially as the "spaceship operator"), is a C++20 language feature that evaluates the relative order of two operands in a single expression. Instead of returning a boolean, it returns a comparison category object indicating whether the left operand is less than, equal to/equivalent to, or greater than the right operand.

```cpp theme={"dark"}
#include <compare>

auto result = lhs <=> rhs;
```

## Comparison Categories

The operator relies on types defined in the `<compare>` header. It does not return an integer; it returns one of three standard comparison category types, which dictate the mathematical properties of the comparison:

1. **`std::strong_ordering`**: Represents a strict total ordering. If `a <=> b == std::strong_ordering::equal`, then `a` and `b` are indistinguishable and perfectly substitutable.
   * Valid values: `less`, `equal`, `greater`.
   * Typical for integral types (`int`, `char`, pointers).
2. **`std::weak_ordering`**: Represents a weak total ordering. If `a <=> b == std::weak_ordering::equivalent`, `a` and `b` evaluate as equivalent for sorting purposes, but their underlying states may differ (e.g., case-insensitive string comparison).
   * Valid values: `less`, `equivalent`, `greater`.
3. **`std::partial_ordering`**: Represents a partial ordering where some values may be incomparable.
   * Valid values: `less`, `equivalent`, `greater`, `unordered`.
   * Typical for floating-point types where `NaN` (Not a Number) cannot be ordered relative to other values.

## Evaluation Mechanics

The result of the `<=>` operator is designed to be compared against literal `0`. The compiler translates traditional relational operators into `<=>` expressions when the traditional operators are not explicitly defined. The spaceship operator is strictly used to rewrite the four relational operators:

* `a < b`  evaluates as `(a <=> b) < 0`
* `a > b`  evaluates as `(a <=> b) > 0`
* `a <= b` evaluates as `(a <=> b) <= 0`
* `a >= b` evaluates as `(a <=> b) >= 0`

Equality (`==`) and inequality (`!=`) are never rewritten to use `operator<=>`. They are resolved strictly using `operator==` (with operand reversal if necessary).

## Defaulting the Operator

When explicitly defaulted inside a class definition, the compiler automatically generates the `<=>` operator using a lexicographical, member-wise comparison. It compares base classes (left-to-right) and non-static data members in their exact order of declaration.

```cpp theme={"dark"}
struct Entity {
    int id;
    double threshold;

    // Instructs the compiler to generate a member-wise three-way comparison.
    // The return type 'auto' allows the compiler to deduce the weakest 
    // comparison category among the members (std::partial_ordering here, due to double).
    auto operator<=>(const Entity&) const = default;
};
```

Defaulting `operator<=>` implicitly declares and defaults `operator==` as well. The generated `operator==` performs direct member-wise equality checks; it does not evaluate `(a <=> b) == 0`. Consequently, a single `= default` declaration provides the class with all six relational operators (`==`, `!=`, `<`, `<=`, `>`, `>=`).

## Custom Implementation

When writing a custom `<=>` operator, you must explicitly specify the return type or use `auto` to let the compiler deduce it based on the returned comparison category.

```cpp theme={"dark"}
struct Wrapper {
    int value;

    // Custom implementation
    std::strong_ordering operator<=>(const Wrapper& rhs) const {
        if (value < rhs.value) return std::strong_ordering::less;
        if (value > rhs.value) return std::strong_ordering::greater;
        return std::strong_ordering::equal;
    }

    // Note: Providing a custom <=> does NOT implicitly generate ==.
    // You must explicitly default or implement operator==.
    bool operator==(const Wrapper&) const = default;
};
```

## Operator Rewriting and Symmetry

The compiler performs expression rewriting to ensure symmetry. If an expression `a < b` is encountered and the left operand `a` does not have a matching `<` or `<=>` operator, the compiler will attempt to rewrite the expression as `0 < (b <=> a)`, reversing the operands and utilizing the right operand's operator. This eliminates the need to write multiple overloads for heterogeneous comparisons (e.g., comparing a class with an `int` in both `obj < 5` and `5 < obj` orders). The same operand reversal mechanism applies to `operator==` for equality checks.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
