27 Iterators library [iterators]

27.1 General [iterators.general]

В этом разделе описываются компоненты, программы C ++ могут использовать для выполнения итерации над containers, streamsи stream buffers.

В следующих подпунктах описываются требования к итератору и компоненты для примитивов итератора, предопределенных итераторов и итераторов потока, как показано в таблице 92.

Таблица 92 - Сводка библиотеки итераторов
Подпункт Заголовок (ы)
[iterator.requirements] Требования
[iterator.primitives] Итераторные примитивы <iterator>
[predef.iterators] Предопределенные итераторы
[stream.iterators] Итераторы потока

27.2 Iterator requirements [iterator.requirements]

27.2.1 In general [iterator.requirements.general]

Итераторы - это обобщение указателей, которые позволяют программе на C ++ единообразно работать с различными структурами данных (контейнерами). Чтобы иметь возможность создавать шаблонные алгоритмы, которые правильно и эффективно работают с различными типами структур данных, библиотека формализует не только интерфейсы, но также семантику и предположения о сложности итераторов. Итератор ввода i поддерживает выражение *i, в результате чего получается значение некоторого типа объекта T, называемого value type итератором. Итератор вывода i имеет непустой набор типов, относящихся writable к итератору; для каждого такого типа допустимо Tвыражение, *i = oгде o - значение типа T. Итератор, i для которого выражение (*i).m четко определено, поддерживает выражение i->m с той же семантикой, что и (*i).m. Для каждого типа итератора, X для которого определено равенство, существует соответствующий целочисленный тип соdifference type знаком, называемый итератором.

Поскольку итераторы являются абстракцией указателей, их семантика является обобщением большей части семантики указателей в C ++. Это гарантирует, что каждый шаблон функции, который принимает итераторы, также работает с обычными указателями. Настоящий стандарт определяет пять категорий итераторов, в соответствии с операциями , определенными на них: input iterators, output iterators, forward iterators, bidirectional iterators и random access iterators, как показано в таблице 93.

Таблица 93 - отношения между категориями итераторов
Произвольный доступ Двунаправленный Вперед Вход
Выход

Прямые итераторы удовлетворяют всем требованиям итераторов ввода и могут использоваться всякий раз, когда указан итератор ввода; Двунаправленные итераторы также удовлетворяют всем требованиям прямых итераторов и могут использоваться всякий раз, когда указан прямой итератор; Итераторы произвольного доступа также удовлетворяют всем требованиям двунаправленных итераторов и могут использоваться всякий раз, когда указан двунаправленный итератор.

Вызываются итераторы, которые дополнительно удовлетворяют требованиям итераторов вывода mutable iterators. Неизменяемые итераторы называются constant iterators.

В дополнение к требованиям этого подпункта для типа итератора должна быть предусмотрена вложенность, typedef-names указанная в [iterator.traits]. [ Note: Либо тип итератора должен предоставлять их typedef-names напрямую (в этом случае получать их iterator_­traits автоматически), либо iterator_­traits специализация должна предоставлять их. ] end note

Итераторы, которые дополнительно удовлетворяют требованию о том, что для целочисленных значений n и значений итераторов с возможностью разыменования a и (a + n), *(a + n) эквивалентно *(addressof(*a) + n), вызываются contiguous iterators. [ Note: Например, тип «указатель на int» является непрерывным итератором, но reverse_­iterator<int *> это не так. Для допустимого диапазона итератора [a,b) с возможностью разыменования aсоответствующий диапазон, обозначенный указателями, равен [addressof(*a),addressof(*a) + (b - a)); b не может быть разыменован. ]end note

Так же, как обычный указатель на массив гарантирует, что существует значение указателя, указывающее за последним элементом массива, так и для любого типа итератора существует значение итератора, указывающее за последним элементом соответствующей последовательности. Эти значения называются past-the-end значениями. Значения итератора ,i для которых выражение *i определенно называется dereferenceable. Библиотека никогда не предполагает, что последние значения могут быть разыменованы. Итераторы также могут иметь особые значения, не связанные с какой-либо последовательностью. [ Example: После объявления неинициализированного указателя x (как в случае int* x;) x всегда следует предполагать, что он имеет единственное значение указателя. ] Результаты большинства выражений не определены для сингулярных значений; единственными исключениями являются уничтожение итератора, содержащего сингулярное значение, присвоение неособого значения итератору, содержащему сингулярное значение, и, для итераторов, удовлетворяющих требованиям, использование итератора с инициализированным значением в качестве источника копирование или перемещение. [ Эта гарантия не предоставляется для инициализации по умолчанию, хотя различие имеет значение только для типов с тривиальными конструкторами по умолчанию, такими как указатели или агрегаты, содержащие указатели. ] В этих случаях единственное значение перезаписывается так же, как и любое другое значение. Разыменяемые значения всегда не единственные.end exampleDefaultConstructible Note: end note

Итератор j вызывается reachable из итератора i тогда и только тогда, когда существует конечная последовательность применений выражения, ++i которое делает i == j. Если j доступен из i, они относятся к элементам той же последовательности.

Большинство алгоритмических шаблонов библиотеки, которые работают со структурами данных, имеют интерфейсы, использующие диапазоны. A range - пара итераторов, обозначающих начало и конец вычисления. Диапазон [i, i) - это пустой диапазон; в общем, диапазон [i, j) относится к элементам в структуре данных, начиная с элемента, на который указывает, i и до, но не включая элемент, на который указывает j. Диапазон [i, j) действителен тогда и только тогда, когда j он доступен из i. Результат применения функций библиотеки к недопустимым диапазонам не определен.

Для всех категорий итераторов требуются только те функции, которые могут быть реализованы для данной категории в постоянное время (с амортизацией). Поэтому в таблицах требований для итераторов нет столбца сложности.

Уничтожение итератора может сделать недействительными указатели и ссылки, ранее полученные от этого итератора.

invalid Итератора является итератор , который может быть вырожденной.261

В следующих разделах, a и b величины означают типа X или const X, difference_­type и reference относятся к типам , iterator_­traits<X>​::​difference_­type и iterator_­traits<X>​::​reference, соответственно, n обозначает значение difference_­type, u, tmpи цветом,m обозначают идентификаторы, r обозначает значение X&, t обозначает значение типа значения T, o обозначает значение некоторого типа который доступен для записи итератору вывода. [ Note: Для типа итератора X должен быть экземпляр iterator_­traits<X>. ] end note

Это определение применяется к указателям, поскольку указатели являются итераторами. Эффект разыменования итератора, который был признан недействительным, не определен.

27.2.2 Iterator [iterator.iterators]

В Iterator требования легли в основу концепции итератора систематики; каждый итератор удовлетворяет Iterator требованиям. Этот набор требований определяет операции для разыменования и увеличения итератора. Большинство алгоритмов потребует дополнительных действий для read или write значения, или обеспечить более богатый набор итератор движений ([forward.iterators], [bidirectional.iterators], [random.access.iterators]).

Тип X удовлетворяет Iterator требованиям, если:

  • X удовлетворяет CopyConstructible, CopyAssignableи Destructible требования ([utility.arg.requirements]) и lvalues типа X являются swappable, и

  • выражения в таблице 94 действительны и имеют указанную семантику.

Таблица 94 - Требования к итератору
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
*r неопределенные Requires: r разыменуемо.
++r X&

27.2.3 Input iterators [input.iterators]

Класс или указатель типа X удовлетворяет требования входного итератора для типа значения ,T если X удовлетворяют Iterator и EqualityComparable требования и выражение , приведенные в таблице 95 , действительны и имеют указанную семантику.

В Таблице 95этот термин the domain of == используется в обычном математическом смысле для обозначения набора значений, для которых == (требуется) определение. Этот набор может меняться со временем. Каждый алгоритм предъявляет дополнительные требования к области == значений используемых итераторов. Эти требования могут быть выведены из использования алгоритма == и !=. [ Example: Вызов find(a,b,x) определяется только в том случае, если значение a имеет свойство, p определенное следующим образом: b имеет свойство, p а значение i имеет свойство p if (*i==x) или if (*i!=x и ++i имеет свойство p). ]end example

Таблица 95 - Требования к итератору ввода (в дополнение к Iterator)
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
a != b контекстно конвертируемый в bool !(a == b) Requires: (a, b) находится в домене ==.
*a reference, конвертируемый в T Requires: a разыменуемо.
Выражение
(void)*a, *a эквивалентно *a.
Если a == b и (a, b) находится в домене, == то *a эквивалентно *b.
a->m (*a).m Requires: a разыменуемо.
++r X& Requires: r разыменуемо.
Postconditions: r разыменован или окончен r ;
любые копии предыдущего значения r больше не должны быть разыменованными или находиться в домене ==.
(void)r++ эквивалентно (void)++r
*r++ конвертируемый в T { T tmp = *r;
++r;
return tmp; }

[ Note: Для итераторов ввода a == b не означает ++a == ++b. (Равенство не гарантирует свойство подстановки или ссылочную прозрачность.) Алгоритмы на итераторах ввода никогда не должны пытаться пройти через один и тот же итератор дважды. Это должны быть single pass алгоритмы. Тип значения T не обязательно должен быть CopyAssignable типом. Эти алгоритмы могут использоваться с istreams в качестве источника входных данных через istream_­iterator шаблон класса. ]end note

27.2.4 Output iterators [output.iterators]

Тип класса или указателя X удовлетворяет требованиям итератора вывода, если X удовлетворяет Iterator требованиям, а выражения в таблице 96 действительны и имеют указанную семантику.

Таблица 96 - Требования к итератору вывода (в дополнение к Iterator)
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
*r = o результат не используется Remarks:  После этой операции r разыменование не требуется.
Postconditions: r является увеличиваемым.
++r X& &r == &++r.
Remarks:  После этой операции r разыменование не требуется.
Postconditions: r является увеличиваемым.
r++ конвертируемый в const X& { X tmp = r;
++r;
return tmp; }
Remarks:  После этой операции r разыменование не требуется.
Postconditions: r является увеличиваемым.
*r++ = o результат не используется Remarks:  После этой операции r разыменование не требуется.
Postconditions: r является увеличиваемым.

[ Note: Единственное допустимое использование - operator* находится в левой части оператора присваивания. Assignment through the same value of the iterator happens only once. Алгоритмы на итераторах вывода никогда не должны пытаться дважды пройти через один и тот же итератор. Это должны быть single pass алгоритмы. Равенство и неравенство нельзя определить. Алгоритмы, которые принимают итераторы вывода, могут использоваться с ostreams в качестве места назначения для размещения данных через ostream_­iterator класс, а также с итераторами вставки и указателями вставки. ]end note

27.2.5 Forward iterators [forward.iterators]

Тип класса или указателя X удовлетворяет требованиям прямого итератора, если

  • X удовлетворяет требованиям input iterator,

  • X удовлетворяет DefaultConstructible requirements,

  • если X изменяемый итератор, reference это ссылка на T; если X постоянный итератор, reference это ссылка на const T,

  • выражения в таблице 97 действительны и имеют указанную семантику, и

  • объекты типа X предлагают многопроходную гарантию, описанную ниже.

Область == прямых итераторов - это область итераторов той же базовой последовательности. Однако итераторы с инициализацией значения могут сравниваться и должны сравниваться наравне с другими итераторами с инициализацией значения того же типа. [ Note: Итераторы с инициализацией значения ведут себя так, как если бы они ссылались на конец одной и той же пустой последовательности. ] end note

Два разыменяемых итератора a и b типа X предлагают multi-pass guarantee if:

  • a == b подразумевает ++a == ++b и

  • X является типом указателя или выражение (void)++X(a), *a эквивалентно выражению *a.

[ Note: Требование, которое a == b подразумевает ++a == ++b (что неверно для итераторов ввода и вывода) и снятие ограничений на количество назначений через изменяемый итератор (которое применяется к итераторам вывода), позволяет использовать многопроходные однонаправленные алгоритмы с прямыми итераторами. ]end note

Таблица 97 - Требования прямого итератора (в дополнение к итератору ввода)
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
r++ конвертируемый в const X& { X tmp = r;
++r;
return tmp; }
*r++ reference

Если a и b равны, то либо a и, либо b разыменуемы, либо ни один из них не разыменован.

Если a и b оба разыменованы, то a == b тогда и только тогда, когда *a и *b привязаны к одному и тому же объекту.

27.2.6 Bidirectional iterators [bidirectional.iterators]

Тип класса или указателя X удовлетворяет требованиям двунаправленного итератора, если, помимо удовлетворения требований для прямых итераторов, допустимы следующие выражения, как показано в таблице 98.

Таблица 98 - Требования к двунаправленному итератору (в дополнение к прямому итератору)
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
--r X& Requires: существует s такое что r == ++s.
Postconditions: r разыменуемо.
--(++r) == r.
--r == --s подразумевает r == s.
&r == &--r.
r-- конвертируемый в const X& { X tmp = r;
--r;
return tmp; }
*r-- reference

[ Note: Двунаправленные итераторы позволяют алгоритмам перемещать итераторы вперед и назад. ]end note

27.2.7 Random access iterators [random.access.iterators]

Тип класса или указателя X удовлетворяет требованиям итератора с произвольным доступом, если, помимо удовлетворения требований для двунаправленных итераторов, допустимы следующие выражения, как показано в таблице 99.

Таблица 99 - Требования к итератору произвольного доступа (в дополнение к двунаправленному итератору)
ВыражениеТип возвратаОперативныйУтверждение / примечание
семантикадо / после состояния
r += n X& { difference_­type 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; Requires: абсолютное значение n находится в диапазоне представимых значений difference_­type.
a - n X { X tmp = a;
return tmp -= n; }
b - a difference_­type return n Requires: существует такое значение n типа difference_­type , что a + n == b.
b == a + (b - a).
a[n] конвертируемый в reference *(a + n)
a < b контекстно конвертируемый в bool b - a > 0 < отношение полного порядка
a > b контекстно конвертируемый в bool b < a > отношение полного порядка, противоположное <.
a >= b контекстно конвертируемый в bool !(a < b)
a <= b контекстно конвертируемый в bool. !(a > b)

27.3 Header <iterator> synopsis [iterator.synopsis]

namespace std {
  // [iterator.primitives], primitives
  template<class Iterator> struct iterator_traits;
  template<class T> struct iterator_traits<T*>;
  template<class T> struct iterator_traits<const T*>;

  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag: public input_iterator_tag { };
  struct bidirectional_iterator_tag: public forward_iterator_tag { };
  struct random_access_iterator_tag: public bidirectional_iterator_tag { };

  // [iterator.operations], iterator operations
  template <class InputIterator, class Distance>
    constexpr void advance(InputIterator& i, Distance n);
  template <class InputIterator>
    constexpr typename iterator_traits<InputIterator>::difference_type
    distance(InputIterator first, InputIterator last);
  template <class InputIterator>
    constexpr InputIterator next(InputIterator x,
      typename iterator_traits<InputIterator>::difference_type n = 1);
  template <class BidirectionalIterator>
    constexpr BidirectionalIterator prev(BidirectionalIterator x,
      typename iterator_traits<BidirectionalIterator>::difference_type n = 1);

  // [predef.iterators], predefined iterators
  template <class Iterator> class reverse_iterator;

  template <class Iterator1, class Iterator2>
    constexpr bool operator==(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);

  template <class Iterator1, class Iterator2>
    constexpr auto operator-(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y) ->decltype(y.base() - x.base());
  template <class Iterator>
    constexpr reverse_iterator<Iterator>
      operator+(
    typename reverse_iterator<Iterator>::difference_type n,
    const reverse_iterator<Iterator>& x);

  template <class Iterator>
    constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);

  template <class Container> class back_insert_iterator;
  template <class Container>
    back_insert_iterator<Container> back_inserter(Container& x);

  template <class Container> class front_insert_iterator;
  template <class Container>
    front_insert_iterator<Container> front_inserter(Container& x);

  template <class Container> class insert_iterator;
  template <class Container>
    insert_iterator<Container> inserter(Container& x, typename Container::iterator i);

  template <class Iterator> class move_iterator;
  template <class Iterator1, class Iterator2>
    constexpr bool operator==(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

  template <class Iterator1, class Iterator2>
    constexpr auto operator-(
    const move_iterator<Iterator1>& x,
    const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base());
  template <class Iterator>
    constexpr move_iterator<Iterator> operator+(
      typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& x);
  template <class Iterator>
    constexpr move_iterator<Iterator> make_move_iterator(Iterator i);

  // [stream.iterators], stream iterators
  template <class T, class charT = char, class traits = char_traits<charT>,
      class Distance = ptrdiff_t>
  class istream_iterator;
  template <class T, class charT, class traits, class Distance>
    bool operator==(const istream_iterator<T,charT,traits,Distance>& x,
            const istream_iterator<T,charT,traits,Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
            const istream_iterator<T,charT,traits,Distance>& y);

  template <class T, class charT = char, class traits = char_traits<charT>>
      class ostream_iterator;

  template<class charT, class traits = char_traits<charT>>
    class istreambuf_iterator;
  template <class charT, class traits>
    bool operator==(const istreambuf_iterator<charT,traits>& a,
            const istreambuf_iterator<charT,traits>& b);
  template <class charT, class traits>
    bool operator!=(const istreambuf_iterator<charT,traits>& a,
            const istreambuf_iterator<charT,traits>& b);

  template <class charT, class traits = char_traits<charT>>
    class ostreambuf_iterator;

  // [iterator.range], range access
  template <class C> constexpr auto begin(C& c) -> decltype(c.begin());
  template <class C> constexpr auto begin(const C& c) -> decltype(c.begin());
  template <class C> constexpr auto end(C& c) -> decltype(c.end());
  template <class C> constexpr auto end(const C& c) -> decltype(c.end());
  template <class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;
  template <class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;
  template <class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c)))
    -> decltype(std::begin(c));
  template <class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c)))
    -> decltype(std::end(c));
  template <class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin());
  template <class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());
  template <class C> constexpr auto rend(C& c) -> decltype(c.rend());
  template <class C> constexpr auto rend(const C& c) -> decltype(c.rend());
  template <class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]);
  template <class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]);
  template <class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);
  template <class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);
  template <class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));
  template <class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));

  // [iterator.container], container access
  template <class C> constexpr auto size(const C& c) -> decltype(c.size());
  template <class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept;
  template <class C> constexpr auto empty(const C& c) -> decltype(c.empty());
  template <class T, size_t N> constexpr bool empty(const T (&array)[N]) noexcept;
  template <class E> constexpr bool empty(initializer_list<E> il) noexcept;
  template <class C> constexpr auto data(C& c) -> decltype(c.data());
  template <class C> constexpr auto data(const C& c) -> decltype(c.data());
  template <class T, size_t N> constexpr T* data(T (&array)[N]) noexcept;
  template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
}

27.4 Iterator primitives [iterator.primitives]

Чтобы упростить задачу определения итераторов, библиотека предоставляет несколько классов и функций:

27.4.1 Iterator traits [iterator.traits]

Чтобы реализовать алгоритмы только в терминах итераторов, часто необходимо определить типы значений и различий, которые соответствуют конкретному типу итератора. Соответственно, требуется, чтобы if Iterator - тип итератора, типы

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::iterator_category

быть определенным как тип различия итератора, тип значения и категория итератора соответственно. Кроме того, типы

iterator_traits<Iterator>::reference
iterator_traits<Iterator>::pointer

должен быть определен как тип ссылки и указателя итератора, то есть для объекта итератора a, тот же тип, что и тип *a и a->, соответственно. В случае итератора вывода типы

iterator_traits<Iterator>::difference_type
iterator_traits<Iterator>::value_type
iterator_traits<Iterator>::reference
iterator_traits<Iterator>::pointer

можно определить как void.

Если Iterator есть действительные ([temp.deduct]) типы элементов difference_­type, value_­type, pointer, reference, и iterator_­category, iterator_­traits<Iterator> должны иметь следующие в качестве публично доступных членов:

  using difference_type   = typename Iterator::difference_type;
  using value_type        = typename Iterator::value_type;
  using pointer           = typename Iterator::pointer;
  using reference         = typename Iterator::reference;
  using iterator_category = typename Iterator::iterator_category;

В противном случае не iterator_­traits<Iterator> будет иметь членов ни с одним из вышеуказанных имен.

Он специализируется на указателях как

namespace std {
  template<class T> struct iterator_traits<T*> {
    using difference_type   = ptrdiff_t;
    using value_type        = T;
    using pointer           = T*;
    using reference         = T&;
    using iterator_category = random_access_iterator_tag;
  };
}

а для указателей на const как

namespace std {
  template<class T> struct iterator_traits<const T*> {
    using difference_type   = ptrdiff_t;
    using value_type        = T;
    using pointer           = const T*;
    using reference         = const T&;
    using iterator_category = random_access_iterator_tag;
  };
}

[ Example: Чтобы реализовать универсальную reverse функцию, программа на C ++ может делать следующее:

template <class BidirectionalIterator>
void reverse(BidirectionalIterator first, BidirectionalIterator last) {
  typename iterator_traits<BidirectionalIterator>::difference_type n =
    distance(first, last);
  --n;
  while(n > 0) {
    typename iterator_traits<BidirectionalIterator>::value_type
     tmp = *first;
    *first++ = *--last;
    *last = tmp;
    n -= 2;
  }
}

end example]

27.4.2 Standard iterator tags [std.iterator.tags]

Часто бывает желательно, чтобы специализация шаблона функции определяла наиболее конкретную категорию аргумента итератора, чтобы функция могла выбрать наиболее эффективный алгоритм во время компиляции. Чтобы облегчить это, в библиотеке представлены category tag классы, которые используются в качестве тегов времени компиляции для выбора алгоритма. Они являются input_­iterator_­tag, output_­iterator_­tag, forward_­iterator_­tag, bidirectional_­iterator_­tag и random_­access_­iterator_­tag. Для каждого итератора типа Iterator, iterator_­traits<Iterator>​::​iterator_­category должны быть определены наиболее конкретной категории тег , который описывает поведение итератора.

namespace std {
  struct input_iterator_tag { };
  struct output_iterator_tag { };
  struct forward_iterator_tag: public input_iterator_tag { };
  struct bidirectional_iterator_tag: public forward_iterator_tag { };
  struct random_access_iterator_tag: public bidirectional_iterator_tag { };
}

[ Example: Для программного итератора BinaryTreeIteratorон может быть включен в категорию двунаправленных итераторов путем специализации iterator_­traits шаблона:

template<class T> struct iterator_traits<BinaryTreeIterator<T>> {
  using iterator_category = bidirectional_iterator_tag;
  using difference_type   = ptrdiff_t;
  using value_type        = T;
  using pointer           = T*;
  using reference         = T&;
};

end example]

[ Example: Если evolve() это хорошо определено для двунаправленных итераторов, но может быть реализовано более эффективно для итераторов с произвольным доступом, то реализация выглядит следующим образом:

template <class BidirectionalIterator>
inline void
evolve(BidirectionalIterator first, BidirectionalIterator last) {
  evolve(first, last,
    typename iterator_traits<BidirectionalIterator>::iterator_category());
}

template <class BidirectionalIterator>
void evolve(BidirectionalIterator first, BidirectionalIterator last,
  bidirectional_iterator_tag) {
  // more generic, but less efficient algorithm
}

template <class RandomAccessIterator>
void evolve(RandomAccessIterator first, RandomAccessIterator last,
  random_access_iterator_tag) {
  // more efficient, but less generic algorithm
}

end example]

27.4.3 Iterator operations [iterator.operations]

Поскольку только итераторы произвольного доступа обеспечивают + и - оператор, библиотека предоставляет два шаблона функции advance и distance. Эти шаблоны функций используют + и - для итераторов произвольного доступа (и, следовательно, являются для них постоянным временем); для входных, прямых и двунаправленных итераторов они используют ++ для реализации линейного времени.

template <class InputIterator, class Distance> constexpr void advance(InputIterator& i, Distance n);

Requires: n должен быть отрицательным только для двунаправленных итераторов и итераторов с произвольным доступом.

Effects: Увеличивает (или уменьшает для отрицательного значения n) ссылкуi на итератор на n.

template <class InputIterator> constexpr typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last);

Effects: Если InputIterator соответствует требованиям итератора произвольного доступа, возвращается (last - first); в противном случае возвращает количество приращений, необходимых для перехода от first к last.

Requires: Если InputIterator удовлетворяет требованиям итератора произвольного доступа, last должен быть доступен first или first должен быть доступен из last; в противном случае last должен быть доступен из first.

template <class InputIterator> constexpr InputIterator next(InputIterator x, typename iterator_traits<InputIterator>::difference_type n = 1);

Effects: Эквивалентен: advance(x, n); return x;

template <class BidirectionalIterator> constexpr BidirectionalIterator prev(BidirectionalIterator x, typename iterator_traits<BidirectionalIterator>::difference_type n = 1);

Effects: Эквивалентен: advance(x, -n); return x;

27.5 Iterator adaptors [predef.iterators]

27.5.1 Reverse iterators [reverse.iterators]

Шаблон класса reverse_­iterator - это адаптер итератора, который выполняет итерацию от конца последовательности, определенной его базовым итератором, до начала этой последовательности. Фундаментальное соотношение между обратным итератором и его соответствующим итератор i устанавливается идентичностью: &*(reverse_­iterator(i)) == &*(i - 1).

27.5.1.1 Class template reverse_­iterator [reverse.iterator]

namespace std {
  template <class Iterator>
  class reverse_iterator {
  public:
    using iterator_type     = Iterator;
    using iterator_category = typename iterator_traits<Iterator>::iterator_category;
    using value_type        = typename iterator_traits<Iterator>::value_type;
    using difference_type   = typename iterator_traits<Iterator>::difference_type;
    using pointer           = typename iterator_traits<Iterator>::pointer;
    using reference         = typename iterator_traits<Iterator>::reference;

    constexpr reverse_iterator();
    constexpr explicit reverse_iterator(Iterator x);
    template <class U> constexpr reverse_iterator(const reverse_iterator<U>& u);
    template <class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);

    constexpr Iterator base() const;      // explicit
    constexpr reference operator*() const;
    constexpr pointer   operator->() const;

    constexpr reverse_iterator& operator++();
    constexpr reverse_iterator  operator++(int);
    constexpr reverse_iterator& operator--();
    constexpr reverse_iterator  operator--(int);

    constexpr reverse_iterator  operator+ (difference_type n) const;
    constexpr reverse_iterator& operator+=(difference_type n);
    constexpr reverse_iterator  operator- (difference_type n) const;
    constexpr reverse_iterator& operator-=(difference_type n);
    constexpr unspecified operator[](difference_type n) const;
  protected:
    Iterator current;
  };

  template <class Iterator1, class Iterator2>
    constexpr bool operator==(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr auto operator-(
      const reverse_iterator<Iterator1>& x,
      const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());
  template <class Iterator>
    constexpr reverse_iterator<Iterator> operator+(
      typename reverse_iterator<Iterator>::difference_type n,
      const reverse_iterator<Iterator>& x);

  template <class Iterator>
    constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);
}

27.5.1.2 reverse_­iterator requirements [reverse.iter.requirements]

Параметр шаблона Iterator должен соответствовать всем требованиям a Bidirectional Iterator.

Кроме того, Iterator должен соответствовать требованиям a, random access iterator если какой-либо из членов operator+ ([reverse.iter.op+]), operator- ([reverse.iter.op-]), operator+= ([reverse.iter.op+=]), operator-= ([reverse.iter.op-=]), operator[] ([reverse.iter.opindex]) или операторов, не являющихся членами operator< ([reverse.iter.op<]), operator> ([reverse.iter.op>]),
operator<= ([reverse.iter.op<=]), operator>= ([reverse.iter.op>=]), operator- ([reverse.iter.opdiff]) или operator+ ([reverse.iter.opsum]) ссылаются таким образом, что требуется instantiation ([temp.inst]).

27.5.1.3 reverse_­iterator operations [reverse.iter.ops]

27.5.1.3.1 reverse_­iterator constructor [reverse.iter.cons]

constexpr reverse_iterator();

Effects: Значение инициализирует current. Операции итератора, применяемые к результирующему итератору, имеют определенное поведение тогда и только тогда, когда соответствующие операции определены в итераторе типа, инициализированном значением Iterator.

constexpr explicit reverse_iterator(Iterator x);

Effects: Инициализируется current с помощью x.

template <class U> constexpr reverse_iterator(const reverse_iterator<U>& u);

Effects: Инициализируется current с помощью u.current.

27.5.1.3.2 reverse_­iterator​::​operator= [reverse.iter.op=]

template <class U> constexpr reverse_iterator& operator=(const reverse_iterator<U>& u);

Effects: Присваивает u.base() текущему.

Returns: *this.

27.5.1.3.3 Conversion [reverse.iter.conv]

constexpr Iterator base() const; // explicit

Returns: current.

27.5.1.3.4 operator* [reverse.iter.op.star]

constexpr reference operator*() const;

Effects: Как будто по:

Iterator tmp = current;
return *--tmp;

27.5.1.3.5 operator-> [reverse.iter.opref]

constexpr pointer operator->() const;

Returns: addressof(operator*()).

27.5.1.3.6 operator++ [reverse.iter.op++]

constexpr reverse_iterator& operator++();

Effects: Как будто по: --current;

Returns: *this.

constexpr reverse_iterator operator++(int);

Effects: Как будто по:

reverse_iterator tmp = *this;
--current;
return tmp;

27.5.1.3.7 operator-- [reverse.iter.op--]

constexpr reverse_iterator& operator--();

Effects: Как будто мимо ++current.

Returns: *this.

constexpr reverse_iterator operator--(int);

Effects: Как будто по:

reverse_iterator tmp = *this;
++current;
return tmp;

27.5.1.3.8 operator+ [reverse.iter.op+]

constexpr reverse_iterator operator+(difference_type n) const;

Returns: reverse_­iterator(current-n).

27.5.1.3.9 operator+= [reverse.iter.op+=]

constexpr reverse_iterator& operator+=(difference_type n);

Effects: Как будто по: current -= n;

Returns: *this.

27.5.1.3.10 operator- [reverse.iter.op-]

constexpr reverse_iterator operator-(difference_type n) const;

Returns: reverse_­iterator(current+n).

27.5.1.3.11 operator-= [reverse.iter.op-=]

constexpr reverse_iterator& operator-=(difference_type n);

Effects: Как будто по: current += n;

Returns: *this.

27.5.1.3.12 operator[] [reverse.iter.opindex]

constexpr unspecified operator[](difference_type n) const;

Returns: current[-n-1].

27.5.1.3.13 operator== [reverse.iter.op==]

template <class Iterator1, class Iterator2> constexpr bool operator==( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current == y.current.

27.5.1.3.14 operator< [reverse.iter.op<]

template <class Iterator1, class Iterator2> constexpr bool operator<( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current > y.current.

27.5.1.3.15 operator!= [reverse.iter.op!=]

template <class Iterator1, class Iterator2> constexpr bool operator!=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current != y.current.

27.5.1.3.16 operator> [reverse.iter.op>]

template <class Iterator1, class Iterator2> constexpr bool operator>( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current < y.current.

27.5.1.3.17 operator>= [reverse.iter.op>=]

template <class Iterator1, class Iterator2> constexpr bool operator>=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current <= y.current.

27.5.1.3.18 operator<= [reverse.iter.op<=]

template <class Iterator1, class Iterator2> constexpr bool operator<=( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y);

Returns: x.current >= y.current.

27.5.1.3.19 operator- [reverse.iter.opdiff]

template <class Iterator1, class Iterator2> constexpr auto operator-( const reverse_iterator<Iterator1>& x, const reverse_iterator<Iterator2>& y) -> decltype(y.base() - x.base());

Returns: y.current - x.current.

27.5.1.3.20 operator+ [reverse.iter.opsum]

template <class Iterator> constexpr reverse_iterator<Iterator> operator+( typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& x);

Returns: reverse_­iterator<Iterator> (x.current - n).

27.5.1.3.21 Non-member function make_­reverse_­iterator() [reverse.iter.make]

template <class Iterator> constexpr reverse_iterator<Iterator> make_reverse_iterator(Iterator i);

Returns: reverse_­iterator<Iterator>(i).

27.5.2 Insert iterators [insert.iterators]

Чтобы можно было обрабатывать вставку так же, как запись в массив,insert iteratorsв библиотеке предусмотрен специальный вид адаптеров итератора, называемый . С обычными классами итераторов

while (first != last) *result++ = *first++;

вызывает [first, last) копирование диапазона в диапазон, начинающийся с результата. Тот же код, result который является итератором вставки, вставит соответствующие элементы в контейнер. Это устройство позволяет всем алгоритмам копирования в библиотеке работать в режиме, insert mode а не в regular overwrite режиме.

Итератор вставки создается из контейнера и, возможно, одного из его итераторов, указывающих на место вставки, если он не находится ни в начале, ни в конце контейнера. Итераторы вставки удовлетворяют требованиям итераторов вывода. operator* возвращает сам итератор вставки. Назначение operator=(const T& x) определяется на итераторах вставки, чтобы разрешить запись в них, оно вставляется x прямо перед тем местом, куда указывает итератор вставки. Другими словами, итератор вставки подобен курсору, указывающему на контейнер, в котором происходит вставка. back_­insert_­iterator вставляет элементы в конец контейнера, front_­insert_­iterator вставляет элементы в начало контейнера и insert_­iterator вставляет элементы, на которые указывает итератор в контейнере. back_­inserter, front_­inserterИ inserter три функции , делающие вставки итераторы из контейнера.

27.5.2.1 Class template back_­insert_­iterator [back.insert.iterator]

namespace std {
  template <class Container>
  class back_insert_iterator {
  protected:
    Container* container;

  public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;

    explicit back_insert_iterator(Container& x);
    back_insert_iterator& operator=(const typename Container::value_type& value);
    back_insert_iterator& operator=(typename Container::value_type&& value);

    back_insert_iterator& operator*();
    back_insert_iterator& operator++();
    back_insert_iterator  operator++(int);
  };

  template <class Container>
    back_insert_iterator<Container> back_inserter(Container& x);
}

27.5.2.2 back_­insert_­iterator operations [back.insert.iter.ops]

27.5.2.2.1 back_­insert_­iterator constructor [back.insert.iter.cons]

explicit back_insert_iterator(Container& x);

Effects: Инициализируется container с помощью addressof(x).

27.5.2.2.2 back_­insert_­iterator​::​operator= [back.insert.iter.op=]

back_insert_iterator& operator=(const typename Container::value_type& value);

Effects: Как будто по: container->push_­back(value);

Returns: *this.

back_insert_iterator& operator=(typename Container::value_type&& value);

Effects: Как будто по: container->push_­back(std​::​move(value));

Returns: *this.

27.5.2.2.3 back_­insert_­iterator​::​operator* [back.insert.iter.op*]

back_insert_iterator& operator*();

Returns: *this.

27.5.2.2.4 back_­insert_­iterator​::​operator++ [back.insert.iter.op++]

back_insert_iterator& operator++(); back_insert_iterator operator++(int);

Returns: *this.

27.5.2.2.5 back_­inserter [back.inserter]

template <class Container> back_insert_iterator<Container> back_inserter(Container& x);

Returns: back_­insert_­iterator<Container>(x).

27.5.2.3 Class template front_­insert_­iterator [front.insert.iterator]

namespace std {
  template <class Container>
  class front_insert_iterator {
  protected:
    Container* container;

  public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;

    explicit front_insert_iterator(Container& x);
    front_insert_iterator& operator=(const typename Container::value_type& value);
    front_insert_iterator& operator=(typename Container::value_type&& value);

    front_insert_iterator& operator*();
    front_insert_iterator& operator++();
    front_insert_iterator  operator++(int);
  };

  template <class Container>
    front_insert_iterator<Container> front_inserter(Container& x);
}

27.5.2.4 front_­insert_­iterator operations [front.insert.iter.ops]

27.5.2.4.1 front_­insert_­iterator constructor [front.insert.iter.cons]

explicit front_insert_iterator(Container& x);

Effects: Инициализируется container с помощью addressof(x).

27.5.2.4.2 front_­insert_­iterator​::​operator= [front.insert.iter.op=]

front_insert_iterator& operator=(const typename Container::value_type& value);

Effects: Как будто по: container->push_­front(value);

Returns: *this.

front_insert_iterator& operator=(typename Container::value_type&& value);

Effects: Как будто по: container->push_­front(std​::​move(value));

Returns: *this.

27.5.2.4.3 front_­insert_­iterator​::​operator* [front.insert.iter.op*]

front_insert_iterator& operator*();

Returns: *this.

27.5.2.4.4 front_­insert_­iterator​::​operator++ [front.insert.iter.op++]

front_insert_iterator& operator++(); front_insert_iterator operator++(int);

Returns: *this.

27.5.2.4.5 front_­inserter [front.inserter]

template <class Container> front_insert_iterator<Container> front_inserter(Container& x);

Returns: front_­insert_­iterator<Container>(x).

27.5.2.5 Class template insert_­iterator [insert.iterator]

namespace std {
  template <class Container>
  class insert_iterator {
  protected:
    Container* container;
    typename Container::iterator iter;

  public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using container_type    = Container;

    insert_iterator(Container& x, typename Container::iterator i);
    insert_iterator& operator=(const typename Container::value_type& value);
    insert_iterator& operator=(typename Container::value_type&& value);

    insert_iterator& operator*();
    insert_iterator& operator++();
    insert_iterator& operator++(int);
  };

  template <class Container>
    insert_iterator<Container> inserter(Container& x, typename Container::iterator i);
}

27.5.2.6 insert_­iterator operations [insert.iter.ops]

27.5.2.6.1 insert_­iterator constructor [insert.iter.cons]

insert_iterator(Container& x, typename Container::iterator i);

Effects: Инициализируется container с помощью addressof(x) и iter с помощью i.

27.5.2.6.2 insert_­iterator​::​operator= [insert.iter.op=]

insert_iterator& operator=(const typename Container::value_type& value);

Effects: Как будто по:

iter = container->insert(iter, value);
++iter;

Returns: *this.

insert_iterator& operator=(typename Container::value_type&& value);

Effects: Как будто по:

iter = container->insert(iter, std::move(value));
++iter;

Returns: *this.

27.5.2.6.3 insert_­iterator​::​operator* [insert.iter.op*]

insert_iterator& operator*();

Returns: *this.

27.5.2.6.4 insert_­iterator​::​operator++ [insert.iter.op++]

insert_iterator& operator++(); insert_iterator& operator++(int);

Returns: *this.

27.5.2.6.5 inserter [inserter]

template <class Container> insert_iterator<Container> inserter(Container& x, typename Container::iterator i);

Returns: insert_­iterator<Container>(x, i).

27.5.3 Move iterators [move.iterators]

Шаблон класса move_­iterator - это адаптер итератора с таким же поведением, что и базовый итератор, за исключением того, что его оператор косвенного обращения неявно преобразует значение, возвращаемое оператором косвенного обращения базового итератора, в rvalue. Некоторые общие алгоритмы можно вызывать с итераторами перемещения, чтобы заменить копирование перемещением.

[Example:

list<string> s;
// populate the list s
vector<string> v1(s.begin(), s.end());          // copies strings into v1
vector<string> v2(make_move_iterator(s.begin()),
                  make_move_iterator(s.end())); // moves strings into v2

end example]

27.5.3.1 Class template move_­iterator [move.iterator]

namespace std {
  template <class Iterator>
  class move_iterator {
  public:
    using iterator_type     = Iterator;
    using iterator_category = typename iterator_traits<Iterator>::iterator_category;
    using value_type        = typename iterator_traits<Iterator>::value_type;
    using difference_type   = typename iterator_traits<Iterator>::difference_type;
    using pointer           = Iterator;
    using reference         = see below;

    constexpr move_iterator();
    constexpr explicit move_iterator(Iterator i);
    template <class U> constexpr move_iterator(const move_iterator<U>& u);
    template <class U> constexpr move_iterator& operator=(const move_iterator<U>& u);

    constexpr iterator_type base() const;
    constexpr reference operator*() const;
    constexpr pointer operator->() const;

    constexpr move_iterator& operator++();
    constexpr move_iterator operator++(int);
    constexpr move_iterator& operator--();
    constexpr move_iterator operator--(int);

    constexpr move_iterator operator+(difference_type n) const;
    constexpr move_iterator& operator+=(difference_type n);
    constexpr move_iterator operator-(difference_type n) const;
    constexpr move_iterator& operator-=(difference_type n);
    constexpr unspecified operator[](difference_type n) const;

  private:
    Iterator current;   // exposition only
  };

  template <class Iterator1, class Iterator2>
    constexpr bool operator==(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator!=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator<=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);
  template <class Iterator1, class Iterator2>
    constexpr bool operator>=(
      const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

  template <class Iterator1, class Iterator2>
    constexpr auto operator-(
      const move_iterator<Iterator1>& x,
      const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base());
  template <class Iterator>
    constexpr move_iterator<Iterator> operator+(
      typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& x);
  template <class Iterator>
    constexpr move_iterator<Iterator> make_move_iterator(Iterator i);
}

Пусть R обозначают iterator_­traits<Iterator>​::​reference. Если is_­reference_­v<R> есть true, то специализация шаблона move_­iterator<Iterator> определяет вложенный тип имени reference как синоним remove_­reference_­t<R>&&, иначе как синоним R.

27.5.3.2 move_­iterator requirements [move.iter.requirements]

Параметр шаблона Iterator должен соответствовать требованиям для input iterator. Кроме того, если реализуется какая-либо из функций обхода с двунаправленным или произвольным доступом, параметр шаблона должен соответствовать требованиям для a Bidirectional Iterator или a Random Access Iterator, соответственно.

27.5.3.3 move_­iterator operations [move.iter.ops]

27.5.3.3.1 move_­iterator constructors [move.iter.op.const]

constexpr move_iterator();

Effects: Создает объект move_­iterator, инициализирующий значение current. Операции итератора, применяемые к результирующему итератору, имеют определенное поведение тогда и только тогда, когда соответствующие операции определены в итераторе типа, инициализированном значением Iterator.

constexpr explicit move_iterator(Iterator i);

Effects: Создаёт move_­iterator, инициализируется current с i.

template <class U> constexpr move_iterator(const move_iterator<U>& u);

Effects: Создаёт move_­iterator, инициализируется current с u.base().

Requires: U конвертируется в Iterator.

27.5.3.3.2 move_­iterator​::​operator= [move.iter.op=]

template <class U> constexpr move_iterator& operator=(const move_iterator<U>& u);

Effects: Назначает u.base() в current.

Requires: U конвертируется в Iterator.

27.5.3.3.3 move_­iterator conversion [move.iter.op.conv]

constexpr Iterator base() const;

Returns: current.

27.5.3.3.4 move_­iterator​::​operator* [move.iter.op.star]

constexpr reference operator*() const;

Returns: static_­cast<reference>(*current).

27.5.3.3.5 move_­iterator​::​operator-> [move.iter.op.ref]

constexpr pointer operator->() const;

Returns: current.

27.5.3.3.6 move_­iterator​::​operator++ [move.iter.op.incr]

constexpr move_iterator& operator++();

Effects: Как будто мимо ++current.

Returns: *this.

constexpr move_iterator operator++(int);

Effects: Как будто по:

move_iterator tmp = *this;
++current;
return tmp;

27.5.3.3.7 move_­iterator​::​operator-- [move.iter.op.decr]

constexpr move_iterator& operator--();

Effects: Как будто мимо --current.

Returns: *this.

constexpr move_iterator operator--(int);

Effects: Как будто по:

move_iterator tmp = *this;
--current;
return tmp;

27.5.3.3.8 move_­iterator​::​operator+ [move.iter.op.+]

constexpr move_iterator operator+(difference_type n) const;

Returns: move_­iterator(current + n).

27.5.3.3.9 move_­iterator​::​operator+= [move.iter.op.+=]

constexpr move_iterator& operator+=(difference_type n);

Effects: Как будто по: current += n;

Returns: *this.

27.5.3.3.10 move_­iterator​::​operator- [move.iter.op.-]

constexpr move_iterator operator-(difference_type n) const;

Returns: move_­iterator(current - n).

27.5.3.3.11 move_­iterator​::​operator-= [move.iter.op.-=]

constexpr move_iterator& operator-=(difference_type n);

Effects: Как будто по: current -= n;

Returns: *this.

27.5.3.3.12 move_­iterator​::​operator[] [move.iter.op.index]

constexpr unspecified operator[](difference_type n) const;

Returns: std​::​move(current[n]).

27.5.3.3.13 move_­iterator comparisons [move.iter.op.comp]

template <class Iterator1, class Iterator2> constexpr bool operator==(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: x.base() == y.base().

template <class Iterator1, class Iterator2> constexpr bool operator!=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: !(x == y).

template <class Iterator1, class Iterator2> constexpr bool operator<(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: x.base() < y.base().

template <class Iterator1, class Iterator2> constexpr bool operator<=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: !(y < x).

template <class Iterator1, class Iterator2> constexpr bool operator>(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: y < x.

template <class Iterator1, class Iterator2> constexpr bool operator>=(const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y);

Returns: !(x < y).

27.5.3.3.14 move_­iterator non-member functions [move.iter.nonmember]

template <class Iterator1, class Iterator2> constexpr auto operator-( const move_iterator<Iterator1>& x, const move_iterator<Iterator2>& y) -> decltype(x.base() - y.base());

Returns: x.base() - y.base().

template <class Iterator> constexpr move_iterator<Iterator> operator+( typename move_iterator<Iterator>::difference_type n, const move_iterator<Iterator>& x);

Returns: x + n.

template <class Iterator> constexpr move_iterator<Iterator> make_move_iterator(Iterator i);

Returns: move_­iterator<Iterator>(i).

27.6 Stream iterators [stream.iterators]

Чтобы алгоритмические шаблоны могли работать напрямую с потоками ввода / вывода, предоставляются соответствующие шаблоны классов, подобные итератору.

[Example:

partial_sum(istream_iterator<double, char>(cin),
  istream_iterator<double, char>(),
  ostream_iterator<double, char>(cout, "\n"));

читает файл, содержащий числа с плавающей запятой cin, и печатает в нем частичные суммы cout. ]end example

27.6.1 Class template istream_­iterator [istream.iterator]

Шаблон класса istream_­iterator - это объект, input iterator который считывает (использует operator>>) последовательные элементы из входного потока, для которого он был создан. После создания и каждый раз ++ использования итератор считывает и сохраняет значение T. Если итератору не удается прочитать и сохранить значение T (fail() в возвращаемом потоке true), итератор становится равным end-of-stream значению итератора. Конструктор без аргументов istream_­iterator() всегда создает объект итератора ввода конца потока, который является единственным допустимым итератором, который может использоваться для условия окончания. Результат operator* итератора в конце потока не определен. Для любого другого итератораconst T& возвращается значение a . Результат operator-> итератора в конце потока не определен. Для любого другого итератораconst T* возвращается значение a . Поведение программы, которая применяется operator++() к итератору конца потока, не определено. Невозможно хранить что-либо в итераторах istream. Тип T должен соответствовать DefaultConstructible, CopyConstructibleи CopyAssignable требованиям.

Два итератора конца потока всегда равны. Итератор конца потока не равен итератору конца потока. Два итератора без конца потока равны, если они построены из одного и того же потока.

namespace std {
  template <class T, class charT = char, class traits = char_traits<charT>,
      class Distance = ptrdiff_t>
  class istream_iterator {
  public:
    using iterator_category = input_iterator_tag;
    using value_type        = T;
    using difference_type   = Distance;
    using pointer           = const T*;
    using reference         = const T&;
    using char_type         = charT;
    using traits_type       = traits;
    using istream_type      = basic_istream<charT,traits>;

    constexpr istream_iterator();
    istream_iterator(istream_type& s);
    istream_iterator(const istream_iterator& x) = default;
    ~istream_iterator() = default;

    const T& operator*() const;
    const T* operator->() const;
    istream_iterator& operator++();
    istream_iterator  operator++(int);
  private:
    basic_istream<charT,traits>* in_stream; // exposition only
    T value;                                // exposition only
  };

  template <class T, class charT, class traits, class Distance>
    bool operator==(const istream_iterator<T,charT,traits,Distance>& x,
            const istream_iterator<T,charT,traits,Distance>& y);
  template <class T, class charT, class traits, class Distance>
    bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
            const istream_iterator<T,charT,traits,Distance>& y);
}

27.6.1.1 istream_­iterator constructors and destructor [istream.iterator.cons]

constexpr istream_iterator();

Effects: Создает итератор конца потока. Если is_­trivially_­default_­constructible_­v<T> есть true, то этот конструктор является конструктором constexpr.

Postconditions: in_­stream == 0.

istream_iterator(istream_type& s);

Effects: Инициализируется in_­stream с помощью addressof(s). value может быть инициализирован во время построения или при первом обращении к нему.

Postconditions: in_­stream == addressof(s).

istream_iterator(const istream_iterator& x) = default;

Effects: Создает копию x. Если is_­trivially_­copy_­constructible_­v<T> есть true, то этот конструктор является тривиальным конструктором копирования.

Postconditions: in_­stream == x.in_­stream.

~istream_iterator() = default;

Effects: Итератор уничтожен. Если is_­trivially_­destructible_­v<T> есть true, то этот деструктор является тривиальным деструктором.

27.6.1.2 istream_­iterator operations [istream.iterator.ops]

const T& operator*() const;

Returns: value.

const T* operator->() const;

Returns: addressof(operator*()).

istream_iterator& operator++();

Requires: in_­stream != 0.

Effects: Как будто по: *in_­stream >> value;

Returns: *this.

istream_iterator operator++(int);

Requires: in_­stream != 0.

Effects: Как будто по:

istream_iterator tmp = *this;
*in_stream >> value;
return (tmp);

template <class T, class charT, class traits, class Distance> bool operator==(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y);

Returns: x.in_­stream == y.in_­stream.

template <class T, class charT, class traits, class Distance> bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y);

Returns: !(x == y)

27.6.2 Class template ostream_­iterator [ostream.iterator]

ostream_­iterator записывает (использует operator<<) последовательные элементы в выходной поток, из которого он был построен. Если он был построен с charT* аргументом конструктора, эта строка, называемая a delimiter string, записывается в поток после каждой записи T . Невозможно получить значение из итератора вывода. Его единственное использование - как итератор вывода в таких ситуациях, как

while (first != last)
  *result++ = *first++;

ostream_­iterator определяется как:

namespace std {
  template <class T, class charT = char, class traits = char_traits<charT>>
  class ostream_iterator {
  public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = charT;
    using traits_type       = traits;
    using ostream_type      = basic_ostream<charT,traits>;

    ostream_iterator(ostream_type& s);
    ostream_iterator(ostream_type& s, const charT* delimiter);
    ostream_iterator(const ostream_iterator& x);
    ~ostream_iterator();
    ostream_iterator& operator=(const T& value);

    ostream_iterator& operator*();
    ostream_iterator& operator++();
    ostream_iterator& operator++(int);
  private:
    basic_ostream<charT,traits>* out_stream;  // exposition only
    const charT* delim;                       // exposition only
  };
}

27.6.2.1 ostream_­iterator constructors and destructor [ostream.iterator.cons.des]

ostream_iterator(ostream_type& s);

Effects: Инициализацию out_­stream с addressof(s) и delim с нулем.

ostream_iterator(ostream_type& s, const charT* delimiter);

Effects: Инициализируется out_­stream с помощью addressof(s) и delim с помощью delimiter.

ostream_iterator(const ostream_iterator& x);

Effects: Создает копию x.

~ostream_iterator();

Effects: Итератор уничтожен.

27.6.2.2 ostream_­iterator operations [ostream.iterator.ops]

ostream_iterator& operator=(const T& value);

Effects: Как будто по:

*out_stream << value;
if (delim != 0)
  *out_stream << delim;
return *this;

ostream_iterator& operator*();

Returns: *this.

ostream_iterator& operator++(); ostream_iterator& operator++(int);

Returns: *this.

27.6.3 Class template istreambuf_­iterator [istreambuf.iterator]

Шаблон класса istreambuf_­iterator определяет объект, input iterator который последовательно читает characters из streambuf, для которого он был создан. operator* обеспечивает доступ к текущему входному символу, если таковой имеется. Каждый раз при operator++ оценке итератор переходит к следующему входному символу. Если достигается конец потока (streambuf_­type​::​sgetc() возвращается traits​::​eof()), итератор становится равным end-of-stream значению итератора. Конструктор по умолчанию istreambuf_­iterator() и конструктор istreambuf_­iterator(0) создают объект-итератор конца потока, подходящий для использования в качестве конца диапазона. Все специализации istreambuf_­iterator должны иметь тривиальный конструктор копирования, конструктор по constexpr умолчанию и тривиальный деструктор.

Результат operator*() итератора конца потока не определен. Для любого другого значения итератора char_­type возвращается значение. Невозможно присвоить символ через итератор ввода.

namespace std {
  template<class charT, class traits = char_traits<charT>>
  class istreambuf_iterator {
  public:
    using iterator_category = input_iterator_tag;
    using value_type        = charT;
    using difference_type   = typename traits::off_type;
    using pointer           = unspecified;
    using reference         = charT;
    using char_type         = charT;
    using traits_type       = traits;
    using int_type          = typename traits::int_type;
    using streambuf_type    = basic_streambuf<charT,traits>;
    using istream_type      = basic_istream<charT,traits>;

    class proxy;                          // exposition only

    constexpr istreambuf_iterator() noexcept;
    istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
    ~istreambuf_iterator() = default;
    istreambuf_iterator(istream_type& s) noexcept;
    istreambuf_iterator(streambuf_type* s) noexcept;
    istreambuf_iterator(const proxy& p) noexcept;
    charT operator*() const;
    istreambuf_iterator& operator++();
    proxy operator++(int);
    bool equal(const istreambuf_iterator& b) const;
  private:
    streambuf_type* sbuf_;                // exposition only
  };

  template <class charT, class traits>
    bool operator==(const istreambuf_iterator<charT,traits>& a,
            const istreambuf_iterator<charT,traits>& b);
  template <class charT, class traits>
    bool operator!=(const istreambuf_iterator<charT,traits>& a,
            const istreambuf_iterator<charT,traits>& b);
}

27.6.3.1 Class template istreambuf_­iterator​::​proxy [istreambuf.iterator.proxy]

namespace std {
  template <class charT, class traits = char_traits<charT>>
  class istreambuf_iterator<charT, traits>::proxy { // exposition only
    charT keep_;
    basic_streambuf<charT,traits>* sbuf_;
    proxy(charT c, basic_streambuf<charT,traits>* sbuf)
      : keep_(c), sbuf_(sbuf) { }
  public:
    charT operator*() { return keep_; }
  };
}

Класс istreambuf_­iterator<charT,traits>​::​proxy предназначен только для экспозиции. Реализации разрешено предоставлять эквивалентную функциональность без предоставления класса с этим именем. Класс istreambuf_­iterator<charT, traits>​::​proxy предоставляет временный заполнитель в качестве возвращаемого значения оператора постинкремента (operator++). Он сохраняет символ, на который указывает предыдущее значение итератора для некоторого возможного доступа в будущем для получения символа.

27.6.3.2 istreambuf_­iterator constructors [istreambuf.iterator.cons]

Для каждого istreambuf_­iterator конструктора в этом разделе итератор конца потока создается тогда и только тогда, когда член, sbuf_­ предназначенный только для представления, инициализируется значением нулевого указателя.

constexpr istreambuf_iterator() noexcept;

Effects: Инициализируется sbuf_­ с помощью nullptr.

istreambuf_iterator(istream_type& s) noexcept;

Effects: Инициализируется sbuf_­ с помощью s.rdbuf().

istreambuf_iterator(streambuf_type* s) noexcept;

Effects: Инициализируется sbuf_­ с помощью s.

istreambuf_iterator(const proxy& p) noexcept;

Effects: Инициализируется sbuf_­ с помощью p.sbuf_­.

27.6.3.3 istreambuf_­iterator operations [istreambuf.iterator.ops]

charT operator*() const

Returns: Персонаж, полученный через streambuf участника sbuf_­->sgetc().

istreambuf_iterator& operator++();

Effects: Как будто мимо sbuf_­->sbumpc().

Returns: *this.

proxy operator++(int);

Returns: proxy(sbuf_­->sbumpc(), sbuf_­).

bool equal(const istreambuf_iterator& b) const;

Returns: true тогда и только тогда, когда оба итератора находятся в конце потока или ни один из них не находится в конце потока, независимо от того, какой streambuf объект они используют.

template <class charT, class traits> bool operator==(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b);

Returns: a.equal(b).

template <class charT, class traits> bool operator!=(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b);

Returns: !a.equal(b).

27.6.4 Class template ostreambuf_­iterator [ostreambuf.iterator]

namespace std {
  template <class charT, class traits = char_traits<charT>>
  class ostreambuf_iterator {
  public:
    using iterator_category = output_iterator_tag;
    using value_type        = void;
    using difference_type   = void;
    using pointer           = void;
    using reference         = void;
    using char_type         = charT;
    using traits_type       = traits;
    using streambuf_type    = basic_streambuf<charT,traits>;
    using ostream_type      = basic_ostream<charT,traits>;

    ostreambuf_iterator(ostream_type& s) noexcept;
    ostreambuf_iterator(streambuf_type* s) noexcept;
    ostreambuf_iterator& operator=(charT c);

    ostreambuf_iterator& operator*();
    ostreambuf_iterator& operator++();
    ostreambuf_iterator& operator++(int);
    bool failed() const noexcept;

  private:
    streambuf_type* sbuf_;                // exposition only
  };
}

Шаблон класса ostreambuf_­iterator последовательно записывает characters в выходной поток, из которого он был построен. Невозможно получить символьное значение из итератора вывода.

27.6.4.1 ostreambuf_­iterator constructors [ostreambuf.iter.cons]

ostreambuf_iterator(ostream_type& s) noexcept;

Requires: s.rdbuf() не должен быть нулевым указателем.

Effects: Инициализируется sbuf_­ с помощью s.rdbuf().

ostreambuf_iterator(streambuf_type* s) noexcept;

Requires: s не должен быть нулевым указателем.

Effects: Инициализируется sbuf_­ с помощью s.

27.6.4.2 ostreambuf_­iterator operations [ostreambuf.iter.ops]

ostreambuf_iterator& operator=(charT c);

Effects: Если failed() уступает false, звонит sbuf_­->sputc(c); в противном случае не имеет никакого эффекта.

Returns: *this.

ostreambuf_iterator& operator*();

Returns: *this.

ostreambuf_iterator& operator++(); ostreambuf_iterator& operator++(int);

Returns: *this.

bool failed() const noexcept;

Returns: true при любом предыдущем использовании member operator=вызов sbuf_­->sputc() возвращается traits​::​eof(); или false иначе.

27.7 Range access [iterator.range]

Помимо того , что доступны через включение <iterator> заголовка, функциональные шаблоны [iterator.range] доступны при любой из следующих заголовков включаются: <array>, <deque>, <forward_­list>, <list>, <map>, <regex>, <set>, <string>, <string_­view>, <unordered_­map>, <unordered_­set>, и <vector>.

template <class C> constexpr auto begin(C& c) -> decltype(c.begin()); template <class C> constexpr auto begin(const C& c) -> decltype(c.begin());

Returns: c.begin().

template <class C> constexpr auto end(C& c) -> decltype(c.end()); template <class C> constexpr auto end(const C& c) -> decltype(c.end());

Returns: c.end().

template <class T, size_t N> constexpr T* begin(T (&array)[N]) noexcept;

Returns: array.

template <class T, size_t N> constexpr T* end(T (&array)[N]) noexcept;

Returns: array + N.

template <class C> constexpr auto cbegin(const C& c) noexcept(noexcept(std::begin(c))) -> decltype(std::begin(c));

Returns: std​::​begin(c).

template <class C> constexpr auto cend(const C& c) noexcept(noexcept(std::end(c))) -> decltype(std::end(c));

Returns: std​::​end(c).

template <class C> constexpr auto rbegin(C& c) -> decltype(c.rbegin()); template <class C> constexpr auto rbegin(const C& c) -> decltype(c.rbegin());

Returns: c.rbegin().

template <class C> constexpr auto rend(C& c) -> decltype(c.rend()); template <class C> constexpr auto rend(const C& c) -> decltype(c.rend());

Returns: c.rend().

template <class T, size_t N> constexpr reverse_iterator<T*> rbegin(T (&array)[N]);

Returns: reverse_­iterator<T*>(array + N).

template <class T, size_t N> constexpr reverse_iterator<T*> rend(T (&array)[N]);

Returns: reverse_­iterator<T*>(array).

template <class E> constexpr reverse_iterator<const E*> rbegin(initializer_list<E> il);

Returns: reverse_­iterator<const E*>(il.end()).

template <class E> constexpr reverse_iterator<const E*> rend(initializer_list<E> il);

Returns: reverse_­iterator<const E*>(il.begin()).

template <class C> constexpr auto crbegin(const C& c) -> decltype(std::rbegin(c));

Returns: std​::​rbegin(c).

template <class C> constexpr auto crend(const C& c) -> decltype(std::rend(c));

Returns: std​::​rend(c).

27.8 Container access [iterator.container]

Помимо того , что доступны через включение <iterator> заголовка, функциональные шаблоны [iterator.container] доступны при любой из следующих заголовков включаются: <array>, <deque>, <forward_­list>, <list>, <map>, <regex>, <set>, <string>, <unordered_­map>, <unordered_­set>, и <vector>.

template <class C> constexpr auto size(const C& c) -> decltype(c.size());

Returns: c.size().

template <class T, size_t N> constexpr size_t size(const T (&array)[N]) noexcept;

Returns: N.

template <class C> constexpr auto empty(const C& c) -> decltype(c.empty());

Returns: c.empty().

template <class T, size_t N> constexpr bool empty(const T (&array)[N]) noexcept;

Returns: false.

template <class E> constexpr bool empty(initializer_list<E> il) noexcept;

Returns: il.size() == 0.

template <class C> constexpr auto data(C& c) -> decltype(c.data()); template <class C> constexpr auto data(const C& c) -> decltype(c.data());

Returns: c.data().

template <class T, size_t N> constexpr T* data(T (&array)[N]) noexcept;

Returns: array.

template <class E> constexpr const E* data(initializer_list<E> il) noexcept;

Returns: il.begin().