std::bidirectional_iterator
Определён в заголовочном файле <iterator> | ||
|---|---|---|
template< class I >
concept bidirectional_iterator =
std::forward_iterator<I> &&
std::derived_from</*ITER_CONCEPT*/<I>, std::bidirectional_iterator_tag> &&
requires(I i) {
{ --i } -> std::same_as<I&>;
{ i-- } -> std::same_as<I>;
};
| (начиная с C++20) |
Концепт bidirectional_iterator уточняет forward_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::bidirectional_iterator_tag>являетсяtrue.) - В противном случае
/*ITER_CONCEPT*/<I>не обозначает тип и приводит к сбою подстановки.
Семантические требования
Двунаправленный итератор r называется декрементируемым тогда и только тогда, когда существует некоторое s, такое что ++s == r.
std::bidirectional_iterator<I> считается реализующим концепт только в том случае, если реализуются все включённые в него концепты; кроме того, для двух объектов a и b типа I выполняются следующие требования:
- Если
aдекрементируем,aвходит в область определения выражений--aиa--. - Предварительный декремент возвращает lvalue, ссылающееся на операнд:
std::addressof(--a) == std::addressof(a). - Постфиксный декремент возвращает предыдущее значение операнда: если
bool(a == b), тоbool(a-- == b). - Постфиксный и префиксный декремент выполняют одинаковое изменение операнда: если
bool(a == b), то после вычисления обоих выраженийa--и--bпо-прежнему выполняетсяbool(a == b). - Инкремент и декремент являются взаимно обратными операциями:
- Если
aинкрементируем иbool(a == b), тоbool(--(++a) == b). - Если
aдекрементируем иbool(a == b), тоbool(++(--a) == b).
Сохранение равенства
Выражения, объявленные в выражениях requires концептов стандартной библиотеки, должны сохранять равенство (кроме случаев, когда указано иное).
Примечания
В отличие от требований LegacyBidirectionalIterator, концепт bidirectional_iterator не требует, чтобы разыменование возвращало lvalue.
Пример
Минимальный двунаправленный итератор.
#include <cstddef>
#include <iterator>
struct SimpleBidiIterator
{
using difference_type = std::ptrdiff_t;
using value_type = int;
int operator*() const;
SimpleBidiIterator& operator++();
SimpleBidiIterator operator++(int)
{
auto tmp = *this;
++*this;
return tmp;
}
SimpleBidiIterator& operator--();
SimpleBidiIterator operator--(int)
{
auto tmp = *this;
--*this;
return tmp;
}
bool operator==(const SimpleBidiIterator&) const;
};
static_assert(std::bidirectional_iterator<SimpleBidiIterator>);
См. также
|
(C++20) | задаёт, что input_iterator является прямым итератором, поддерживающим сравнение на равенство и многопроходный обход (концепт) |
|
(C++20) | задаёт, что bidirectional_iterator является итератором произвольного доступа, поддерживающим перемещение за постоянное время и индексирование (концепт) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/bidirectional_iterator