CodeNebula
C++20stladvanced

std::totally_ordered (C++20 Addition)

C++20 · The Big Four · Compiler flag: -std=c++20

Explanation

Concept that checks if a type supports all six comparison operators (`==`, `!=`, `<`, `>`, `<=`, `>=`) and that the ordering is consistent (a total order). Enables use in sorting and ordered containers.

Real-World Scenario

Constrain a priority queue to only accept types with a total ordering, guaranteeing deterministic sorting behavior.

Quick Snippet

snippet.cpp
#include <concepts>

template<std::totally_ordered T>
class PriorityQueue {
    std::vector<T> heap;
public:
    void push(T value) {
        heap.push_back(std::move(value));
        std::ranges::push_heap(heap);
    }
    T pop() {
        std::ranges::pop_heap(heap);
        T top = std::move(heap.back());
        heap.pop_back();
        return top;
    }
};

Full Example

totally_ordered.cpp
// CodeNebula - C++20 Example: std::totally_ordered Concept
// Compile: g++ -std=c++20 -Wall -Wextra -o example totally_ordered.cpp

// std::totally_ordered<T> requires ==, !=, <, >, <=, >= operators that
// establish a strict total order. This is essential for sorting and
// ordered containers.

#include <algorithm>
#include <concepts>
#include <iostream>
#include <string>
#include <vector>

struct Temperature {
    double celsius;
    auto operator<=>(const Temperature&) const = default;  // C++20 spaceship
};

// Clamp a value to a range (requires total ordering)
template <std::totally_ordered T>
T clamp_value(const T& val, const T& low, const T& high) {
    if (val < low) return low;
    if (val > high) return high;
    return val;
}

// Find min and max in a range
template <std::totally_ordered T>
std::pair<T, T> min_max(const std::vector<T>& vec) {
    T lo = vec[0], hi = vec[0];
    for (const auto& v : vec) {
        if (v < lo) lo = v;
        if (v > hi) hi = v;
    }
    return {lo, hi};
}

// Insertion sort (requires totally_ordered)
template <std::totally_ordered T>
void insertion_sort(std::vector<T>& vec) {
    for (std::size_t i = 1; i < vec.size(); ++i) {
        T key = vec[i];
        int j = static_cast<int>(i) - 1;
        while (j >= 0 && vec[j] > key) {
            vec[j + 1] = vec[j];
            --j;
        }
        vec[j + 1] = key;
    }
}

int main() {
    // Clamp values
    std::cout << "clamp(15, 0, 10): " << clamp_value(15, 0, 10) << "\n";
    std::cout << "clamp(-5, 0, 10): " << clamp_value(-5, 0, 10) << "\n";
    std::cout << "clamp(5, 0, 10): " << clamp_value(5, 0, 10) << "\n";

    // Min/max
    std::vector<int> nums = {38, 12, 95, 7, 63};
    auto [lo, hi] = min_max(nums);
    std::cout << "\nMin: " << lo << ", Max: " << hi << "\n";

    // Sort integers
    insertion_sort(nums);
    std::cout << "Sorted: ";
    for (int n : nums) std::cout << n << " ";
    std::cout << "\n";

    // Sort strings (lexicographic total order)
    std::vector<std::string> words = {"cherry", "apple", "banana"};
    insertion_sort(words);
    std::cout << "Sorted: ";
    for (const auto& w : words) std::cout << w << " ";
    std::cout << "\n";

    // Temperature with defaulted <=>
    Temperature t1{36.6}, t2{37.5}, t3{35.0};
    std::cout << "\n36.6 < 37.5: " << (t1 < t2) << "\n";
    std::cout << "totally_ordered<Temperature>: "
              << std::totally_ordered<Temperature> << "\n";

    return 0;
}

// Expected output:
// clamp(15, 0, 10): 10
// clamp(-5, 0, 10): 0
// clamp(5, 0, 10): 5
//
// Min: 7, Max: 95
// Sorted: 7 12 38 63 95
// Sorted: apple banana cherry
//
// 36.6 < 37.5: 1
// totally_ordered<Temperature>: 1
Run command
g++ -std=c++20 -Wall -Wextra -o example totally_ordered.cpp