CodeNebula
C++20stladvanced

std::ranges::random_access_range (C++20 Addition)

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

Explanation

Concept for ranges supporting constant-time indexed access and arbitrary iterator jumps. Enables O(1) element access and efficient sorting.

Real-World Scenario

Implement a binary search on a sorted leaderboard stored in a random-access container.

Quick Snippet

snippet.cpp
#include <ranges>

template<std::ranges::random_access_range R>
auto binary_search(R&& r, const std::ranges::range_value_t<R>& val) {
    auto lo = std::ranges::begin(r);
    auto hi = std::ranges::end(r);
    while (lo < hi) {
        auto mid = lo + (hi - lo) / 2;
        if (*mid < val) lo = mid + 1; else hi = mid;
    }
    return lo;
}

Full Example

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

#include <ranges>
#include <vector>
#include <deque>
#include <list>
#include <array>
#include <algorithm>
#include <iostream>

// std::ranges::random_access_range requires O(1) access to any
// element by index, supporting iterator arithmetic (+, -, []).

// Binary search using random access iterators
template <std::ranges::random_access_range R, typename T>
bool binary_search_range(R&& r, const T& target) {
    auto lo = std::ranges::begin(r);
    auto hi = std::ranges::end(r);
    while (lo < hi) {
        auto mid = lo + (hi - lo) / 2;
        if (*mid == target) return true;
        else if (*mid < target) lo = mid + 1;
        else hi = mid;
    }
    return false;
}

// Get the nth element from end
template <std::ranges::random_access_range R>
auto nth_from_end(R&& r, std::ranges::range_difference_t<R> n) {
    return *(std::ranges::end(r) - n - 1);
}

int main() {
    // Random access containers
    static_assert(std::ranges::random_access_range<std::vector<int>>);
    static_assert(std::ranges::random_access_range<std::deque<int>>);
    static_assert(std::ranges::random_access_range<std::array<int, 5>>);
    static_assert(std::ranges::random_access_range<int[5]>);

    // list is NOT random access
    static_assert(!std::ranges::random_access_range<std::list<int>>);

    std::vector<int> sorted = {2, 5, 8, 12, 16, 23, 38, 56, 72};

    std::cout << "Search for 23: " << std::boolalpha
              << binary_search_range(sorted, 23) << "\n";
    std::cout << "Search for 10: "
              << binary_search_range(sorted, 10) << "\n";

    std::cout << "2nd from end: " << nth_from_end(sorted, 2) << "\n";
    std::cout << "Last element: " << nth_from_end(sorted, 0) << "\n";

    // Direct subscript access via ranges
    std::cout << "Element at index 3: " << sorted[3] << "\n";

    // iota_view is random access
    auto iota = std::views::iota(0, 10);
    static_assert(std::ranges::random_access_range<decltype(iota)>);
    std::cout << "iota[7]: " << iota[7] << "\n";

    // ranges::sort requires random_access_range
    std::vector<int> unsorted = {5, 3, 8, 1, 9, 2};
    std::ranges::sort(unsorted);
    std::cout << "Sorted: ";
    for (int n : unsorted) std::cout << n << " ";
    std::cout << "\n";
    return 0;
}
Run command
g++ -std=c++20 -Wall -Wextra -o example ranges_random_access_range.cpp