Spec-Zone.ru › C++

std::random_access_iterator

Определён в заголовочном файле <iterator>
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>>;
        };
(начиная с C++20)

Концепция random_access_iterator уточняет bidirectional_iterator, добавляя поддержку перемещения за постоянное время с помощью операторов +=, +, -= и -, вычисления расстояния за постоянное время с помощью - и индексирования с помощью оператора индексации [].

Определение концепции итератора

Определение этой концепции задано с помощью шаблона псевдонима /*ITER_CONCEPT*/, используемого только для описания.

Чтобы определить /*ITER_CONCEPT*/<I>, пусть ITER_TRAITS<I> обозначает I, если специализация std::iterator_traits<I> получена из первичного шаблона, и std::iterator_traits<I> в противном случае:

  • Если ITER_TRAITS<I>::iterator_concept допустимо и обозначает тип, /*ITER_CONCEPT*/<I> обозначает этот тип.
  • В противном случае, если ITER_TRAITS<I>::iterator_category допустимо и обозначает тип, /*ITER_CONCEPT*/<I> обозначает этот тип.
  • В противном случае, если std::iterator_traits<I> получено из первичного шаблона, /*ITER_CONCEPT*/<I> обозначает std::random_access_iterator_tag.
    (То есть предполагается, что std::derived_from</*ITER_CONCEPT*/<I>, std::random_access_iterator_tag> является true.)
  • В противном случае /*ITER_CONCEPT*/<I> не обозначает тип и приводит к ошибке подстановки.

Семантические требования

Пусть a и b — допустимые итераторы типа I, такие что b достижим из a, а n — значение типа std::iter_difference_t<I>, равное b - a. std::random_access_iterator<I> моделируется только в том случае, если моделируются все включаемые им концепции и выполняются следующие условия:

  • (a += n) равно b.
  • std::addressof(a += n) равно std::addressof(a). [1]
  • (a + n) равно (a += n).
  • (a + n) равно (n + a).
  • Для любых двух положительных целых чисел x и y, если a + (x + y) допустимо, то a + (x + y) равно (a + x) + y.
  • a + 0 равно a.
  • Если (a + (n - 1)) допустимо, то --b равно (a + (n - 1)).
  • (b += -n) и (b -= n) равны a.
  • std::addressof(b -= n) равно std::addressof(b). [1]
  • (b - n) равно (b -= n).
  • Если b допускает разыменование, то a[n] допустимо и равно *b.
  • bool(a <= b) является true.
  • Каждая требуемая операция выполняется за постоянное время.

Обратите внимание: std::addressof возвращает адрес объекта-итератора, а не адрес объекта, на который указывает итератор. То есть operator+= и operator-= должны возвращать ссылку на *this.

Сохранение равенства

От выражений, объявленных в requires-выражениях концепций стандартной библиотеки, требуется сохранять равенство (если не указано иное).

Неявные варианты выражений

requires-выражение, использующее выражение, не изменяющее некоторый константный операнд-левостороннее значение, также требует неявных вариантов выражений.

Примечания

В отличие от требований LegacyRandomAccessIterator, концепция random_access_iterator не требует, чтобы разыменование возвращало левостороннее значение.

Пример

Демонстрируется возможная реализация std::distance с помощью концепций C++20.

#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);
}

См. также

bidirectional_iterator
(C++20)
задаёт, что forward_iterator является двунаправленным итератором, поддерживающим перемещение назад
(концепция)
contiguous_iterator
(C++20)
задаёт, что random_access_iterator является непрерывным итератором, ссылающимся на элементы, расположенные в памяти непрерывно
(концепция)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/random_access_iterator

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API