Последовательные итераторы (Forward iterators)
Класс или встроенный тип X удовлетворяет требованиям последовательного итератора, если справедливы следующие выражения:
Таблица 4. Требования последовательного итератора
выражение |
возвращаемый тип |
семантика исполнения |
утверждение/примечание состояние до/после |
X u; |
- |
- |
примечание: u может иметь исключительное значение. примечание: предполагается деструктор. |
X() |
- |
- |
примечание: X() может быть исключительным. |
X(a); |
- |
- |
a == X(a) |
X u(a); X u = a; |
- |
X u; u = a; |
после: u == a. |
a == b |
обратимый в bool |
- |
== - это отношение эквивалентности. |
a!= b |
обратимый в bool |
!(a == b) |
- |
r = a |
X& |
- |
после: r == a. |
*a |
обратимый в T |
- |
до: a - разыменовываемое. a==b подразумевает *a==*b. Если X - модифицируемый, то *a = t - допустимо. |
++r |
X& |
- |
до: r - разыменовываемое. после: r - разыменовываемое или r - законечное. r == s и r - разыменовываемое подразумевает ++r==++s. &r==&++r. |
r++ |
X |
{X tmp = r; ++ r; return tmp;} |
- |
ПРИМЕЧАНИЕ.Тот факт, что r == s подразумевает ++r == ++s (что неверно для итераторов ввода и вывода) и что удалено ограничение на число присваиваний через итератор (которое применяется к итераторам вывода), позволяет использование многопроходных однонаправленных алгоритмов с последовательными итераторами.
Двунаправленные итераторы (Bidirectional iterators)
Класс или встроенный тип X удовлетворяет требованиям двунаправленного итератора, если к таблице, которая определяет последовательные итераторы, мы добавим следующие строки:
Таблица 5. Требования двунаправленного итератора (в дополнение к последовательному итератору)
выражение |
возвращаемый тип |
семантика исполнения |
утверждение/примечание состояние до/после |
--r |
X& |
- |
до: существует s такое, что r==++s. после: s - разыменовываемое. --(++r)==r. --r==--s подразумевает r==s.&r==&--r. |
r-- |
X |
{X tmp = r; - -r; return tmp;} |
- |
ПРИМЕЧАНИЕ.Двунаправленные итераторы позволяют алгоритмам перемещать итераторы назад так же, как вперёд.
Итераторы произвольного доступа (Random access iterators)
Класс или встроенный тип X удовлетворяет требованиям итераторов произвольного доступа, если к таблице, которая определяет двунаправленные итераторы, мы добавим следующие строки:
Таблица 6: Требования итератора произвольного доступа (в дополнение к двунаправленному итератору)
выражение |
возвращаемый тип |
семантика исполнения |
утверждение/примечание состояние до/после |
r += n |
X& |
{Distance m = n; if(m ›= 0) while(m--) ++r; else while(m++) --r; return r;} |
- |
a + n n + a |
X |
{X tmp = a; return tmp += n;} |
a + n == n + a. |
r -= n |
X& |
return r += -n; |
- |
a - n |
X |
{X tmp = a; return tmp -= n;} |
- |
b - a |
Distance |
- |
до: существует значение n типа Distance такое, что a+n=b. b==a+(b-a). |
a[n] |
обратимый в T |
*(a + n) |
- |
a ‹ b |
обратимый в bool |
b - a › 0 |
‹ - это отношение полного упорядочения |
a › b |
обратимый в bool |
b ‹ a |
› - это отношение полного упорядочения, противоположное ‹. |
a ›= b |
обратимый в bool |
!(a ‹ b) |
- |
a ‹= b |
обратимый в bool |
!(a › b) |
- |
Теги итераторов (Iterator tags)
Чтобы осуществлять алгоритмы только в терминах итераторов, часто бывает необходимо вывести тип значения и тип расстояния из итератора. Для решения этой задачи требуется, чтобы для итератора i любой категории, отличной от итератора вывода, выражение value_type(i) возвращало (T*)(0), а выражение distance_type(i) возвращало (Distance*)(0). Для итераторов вывода эти выражения не требуются.
Примеры использования тегов итераторов
Для всех типов обычных указателей мы можем определить value_type и distance_type с помощью следующего:
template ‹class T›
inline T* value_type(const T*) {return (T*)(0);}
template ‹class T›
inline ptrdiff_t* distance_type(const T*) {return (ptrdiff_t*)(0);}
Тогда, если мы хотим осуществить обобщённую функцию reverse, мы пишем следующее:
template ‹class BidirectionalIterator›
inline void reverse(BidirectionalIterator first, BidirectionalIterator last) {
_reverse(first, last, value_type(first), distance_type(first));
}
где _reverse определена следующим образом:
template ‹class BidirectionalIterator, class T, class Distance›
void _reverse(BidirectionalIterator first, BidirectionalIterator last, T*, Distance*) {
Читать дальше