std::random...ess_iterator(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

🌸 NAME 🌸

std::random_access_iterator β€” okay so this is, like, the std::random_access_iterator concept from the C++ Standard Library, and it's a whole vibe. Periodt. πŸ’…


✨ Synopsis ✨

Defined in header <iterator>, and this whole thing is since C++20 πŸŽ€

template< class I >
concept random_access_iterator =
    std::bidirectional_iterator<I> &&
    std::derived_from</*ITER_CONCEPT*/<I>, std::random_access_iterator_tag> &&
    std::totally_ordered<I> &&
    std::sized_sentinel_for<I, I> &&
    requires(I i, const I j, const std::iter_difference_t<I> n) {
        { i += n } -> std::same_as<I&>;
        { j +  n } -> std::same_as<I>;
        { n +  j } -> std::same_as<I>;
        { i -= n } -> std::same_as<I&>;
        { j -  n } -> std::same_as<I>;
        {  j[n]  } -> std::same_as<std::iter_reference_t<I>>;
    };

So the concept random_access_iterator refines bidirectional_iterator by adding support for:

  • constant time advancement with the +=, +, -=, and - operators πŸƒβ€β™€οΈπŸ’¨
  • constant time computation of distance with - πŸ“
  • array notation with subscripting [] πŸ”’

It's giving "I can jump anywhere instantly and you can't stop me" energy, honestly. πŸ‘‘


πŸ’– Notes πŸ’–

Unlike the LegacyRandomAccessIterator requirements, the random_access_iterator concept does not require dereference to return an lvalue. No cap. So like, don't assume you're getting a reference you can assign through β€” the concept is chill about that. πŸ™ˆ


πŸŽ€ Example πŸŽ€

The page literally says // Run this code before this one, so go run it, bestie β€” it demonstrates a possible implementation of std::distance via C++20 concepts. πŸ§šβ€β™€οΈ

#include <iterator>

namespace cxx20
{
    template<std::input_or_output_iterator Iter>
    constexpr std::iter_difference_t<Iter> distance(Iter first, Iter last)
    {
        if constexpr(std::random_access_iterator<Iter>)
            return last - first;
        else
        {
            std::iter_difference_t<Iter> result{};
            for (; first != last; ++first)
                ++result;
            return result;
        }
    }
}

int main()
{
    static constexpr auto il = {3, 1, 4};

    static_assert(std::random_access_iterator<decltype(il.begin())> &&
                  cxx20::distance(il.begin(), il.end()) == 3 &&
                  cxx20::distance(il.end(), il.begin()) == -3);
}

Like, the way this just branches at compile time and picks the fast path if the iterator is random access? Obsessed. πŸ”₯


πŸ¦‹ See also πŸ¦‹

  • bidirectional_iterator (concept, C++20) β€” specifies that a forward_iterator is a bidirectional iterator, supporting movement backwards. So it can go back and forth, but not necessarily zoom around. πŸ¦‹
  • contiguous_iterator (concept, C++20) β€” specifies that a random_access_iterator is a contiguous iterator, referring to elements that are contiguous in memory. Like, they're literally sitting next to each other in RAM. Iconic. 🌈

Source: http://cppreference.com Β· version/date: 2024.06.10 Β· page: std::random...ess_iterator(3)

That's the whole page, bestie β€” every flag, every concept, every line of code, all accounted for. Mwah. πŸ’‹βœ¨

πŸ“¦ where this page comes from