std::contiguous_iterator
Определён в заголовочном файле <iterator> | ||
|---|---|---|
template< class I >
concept contiguous_iterator =
std::random_access_iterator<I> &&
std::derived_from</*ITER_CONCEPT*/<I>, std::contiguous_iterator_tag> &&
std::is_lvalue_reference_v<std::iter_reference_t<I>> &&
std::same_as<std::iter_value_t<I>,
std::remove_cvref_t<std::iter_reference_t<I>>> &&
requires(const I& i) {
{ std::to_address(i) } ->
std::same_as<std::add_pointer_t<std::iter_reference_t<I>>>;
};
| (начиная с C++20) |
Концепт contiguous_iterator уточняет random_access_iterator, гарантируя, что обозначаемые элементы хранятся в памяти непрерывно.
| Пусть итератор
Это означает, что программа не может полагаться на побочные эффекты разыменования, инкремента или декремента непрерывного итератора | (начиная с C++26) |
Определение концепта итератора
Определение этого концепта задаётся с помощью шаблона псевдонима, предназначенного только для описания, /*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::contiguous_iterator_tag>— этоfalse.) - Иначе
/*ITER_CONCEPT*/<I>не обозначает тип и приводит к сбою подстановки.
Семантические требования
Пусть a и b — разыменовываемые итераторы, а c — неразыменовываемый итератор типа I, такой что b достижим из a, а c достижим из b. Тип I моделирует contiguous_iterator только в том случае, если моделируются все включаемые им концепты и выполняются все следующие условия:
-
std::to_address(a) == std::addressof(*a). -
std::to_address(b) == std::to_address(a) + std::iter_difference_t<I>(b - a). -
std::to_address(c) == std::to_address(a) + std::iter_difference_t<I>(c - a). -
std::to_address(I{})корректно определено. -
ranges::iter_move(a)имеет тот же тип, категорию значения и эффекты, что иstd::move(*a). - Если
ranges::iter_swap(a, b)корректно сформировано, оно имеет эффекты, эквивалентныеranges::swap(*a, *b).
Сохранение равенства
Выражения, объявленные в выражениях requires стандартных библиотечных концептов, должны сохранять равенство (если не указано иное).
Неявные варианты выражений
Выражение requires, в котором используется выражение, не изменяющее некоторый константный операнд-левостороннее значение, также требует наличия неявных вариантов выражений.
Примечания
Концепт contiguous_iterator моделируется всеми типами указателей на полные объектные типы.
Типы итераторов стандартной библиотеки, которые в C++17 должны удовлетворять требованиям LegacyContiguousIterator, в C++20 также должны моделировать contiguous_iterator.
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение согласно опубликованному стандарту | Корректное поведение |
|---|---|---|---|
| LWG 3607 | C++20 |
contiguous_iterator мог иметь пользовательскиеповедения ranges::iter_move и ranges::iter_swap | запрещено |
| LWG 4170 | C++20 | пара инициализированных значением contiguous_iteratorмогла не представлять пустой диапазон | гарантировано |
См. также
|
(C++20) | задаёт, что bidirectional_iterator является итератором произвольного доступа, поддерживающим перемещение за постоянное время и индексирование (концепт) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/contiguous_iterator