Namespaces
Variants

std:: random_access_iterator

From cppreference.net
Iterator library
Iterator concepts
random_access_iterator
(C++20)


Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
Определено в заголовочном файле <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 выражениях концепций стандартной библиотеки, должны быть equality-preserving (если не указано иное).

Вариации неявных выражений

Выражение requires expression , использующее выражение, которое является немодифицирующим для некоторого константного lvalue операнда, также требует неявных вариаций выражений .

Примечания

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

Пример

Демонстрирует возможную реализацию 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);
}

Смотрите также

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