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);
}
См. также
|
(C++20) | задаёт, что forward_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