std:: random_access_iterator
|
Определено в заголовочном файле
<iterator>
|
||
|
template
<
class
I
>
concept random_access_iterator
=
|
(начиная с 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); }
Смотрите также
|
(C++20)
|
определяет, что
forward_iterator
является двунаправленным итератором, поддерживающим перемещение назад
(концепт) |
|
(C++20)
|
определяет, что
random_access_iterator
является непрерывным итератором, ссылающимся на элементы, расположенные непрерывно в памяти
(концепт) |