В этом разделе описываются компоненты, программы C ++ могут использовать для выполнения итерации над containers, streamsи stream buffers.
В следующих подпунктах описываются требования к итератору и компоненты для примитивов итератора, предопределенных итераторов и итераторов потока, как показано в таблице 92.
Подпункт | Заголовок (ы) | |
[iterator.requirements] | Требования | |
[iterator.primitives] | Итераторные примитивы | <iterator> |
[predef.iterators] | Предопределенные итераторы | |
[stream.iterators] | Итераторы потока |
Итераторы - это обобщение указателей, которые позволяют программе на 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.
Произвольный доступ | → Двунаправленный | → Вперед | → Вход |
→ Выход |
Прямые итераторы удовлетворяют всем требованиям итераторов ввода и могут использоваться всякий раз, когда указан итератор ввода; Двунаправленные итераторы также удовлетворяют всем требованиям прямых итераторов и могут использоваться всякий раз, когда указан прямой итератор; Итераторы произвольного доступа также удовлетворяют всем требованиям двунаправленных итераторов и могут использоваться всякий раз, когда указан двунаправленный итератор.
Вызываются итераторы, которые дополнительно удовлетворяют требованиям итераторов вывода 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 example DefaultConstructible Note: — end note
Итератор j вызывается reachable из итератора i тогда и только тогда, когда существует конечная последовательность применений выражения, ++i которое делает i == j. Если j доступен из i, они относятся к элементам той же последовательности.
Большинство алгоритмических шаблонов библиотеки, которые работают со структурами данных, имеют интерфейсы, использующие диапазоны. A range - пара итераторов, обозначающих начало и конец вычисления. Диапазон [i, i) - это пустой диапазон; в общем, диапазон [i, j) относится к элементам в структуре данных, начиная с элемента, на который указывает, i и до, но не включая элемент, на который указывает j. Диапазон [i, j) действителен тогда и только тогда, когда j он доступен из i. Результат применения функций библиотеки к недопустимым диапазонам не определен.
Для всех категорий итераторов требуются только те функции, которые могут быть реализованы для данной категории в постоянное время (с амортизацией). Поэтому в таблицах требований для итераторов нет столбца сложности.
Уничтожение итератора может сделать недействительными указатели и ссылки, ранее полученные от этого итератора.
В следующих разделах, 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
Это определение применяется к указателям, поскольку указатели являются итераторами. Эффект разыменования итератора, который был признан недействительным, не определен.
В Iterator требования легли в основу концепции итератора систематики; каждый итератор удовлетворяет Iterator требованиям. Этот набор требований определяет операции для разыменования и увеличения итератора. Большинство алгоритмов потребует дополнительных действий для read или write значения, или обеспечить более богатый набор итератор движений ([forward.iterators], [bidirectional.iterators], [random.access.iterators]).
Тип X удовлетворяет Iterator требованиям, если:
X удовлетворяет CopyConstructible, CopyAssignableи Destructible требования ([utility.arg.requirements]) и lvalues типа X являются swappable, и
выражения в таблице 94 действительны и имеют указанную семантику.
Выражение | Тип возврата | Оперативный | Утверждение / примечание |
семантика | до / после состояния | ||
*r | неопределенные | Requires: r разыменуемо. | |
++r | X& |
Класс или указатель типа 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
Выражение | Тип возврата | Оперативный | Утверждение / примечание |
семантика | до / после состояния | ||
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
Тип класса или указателя X удовлетворяет требованиям итератора вывода, если X удовлетворяет Iterator требованиям, а выражения в таблице 96 действительны и имеют указанную семантику.
Выражение | Тип возврата | Оперативный | Утверждение / примечание |
семантика | до / после состояния | ||
*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
Тип класса или указателя 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
Выражение | Тип возврата | Оперативный | Утверждение / примечание |
семантика | до / после состояния | ||
r++ | конвертируемый в const X& |
{ X tmp = r; ++r; return tmp; } | |
*r++ | reference |
Тип класса или указателя X удовлетворяет требованиям двунаправленного итератора, если, помимо удовлетворения требований для прямых итераторов, допустимы следующие выражения, как показано в таблице 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 |
Тип класса или указателя X удовлетворяет требованиям итератора с произвольным доступом, если, помимо удовлетворения требований для двунаправленных итераторов, допустимы следующие выражения, как показано в таблице 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) |
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; }
Чтобы упростить задачу определения итераторов, библиотека предоставляет несколько классов и функций:
Чтобы реализовать алгоритмы только в терминах итераторов, часто необходимо определить типы значений и различий, которые соответствуют конкретному типу итератора. Соответственно, требуется, чтобы 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 ]
Поскольку только итераторы произвольного доступа обеспечивают + и - оператор, библиотека предоставляет два шаблона функции advance и distance. Эти шаблоны функций используют + и - для итераторов произвольного доступа (и, следовательно, являются для них постоянным временем); для входных, прямых и двунаправленных итераторов они используют ++ для реализации линейного времени.
template <class InputIterator, class Distance>
constexpr void advance(InputIterator& i, Distance n);
Requires: 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);
template <class BidirectionalIterator>
constexpr BidirectionalIterator prev(BidirectionalIterator x,
typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
Шаблон класса reverse_iterator - это адаптер итератора, который выполняет итерацию от конца последовательности, определенной его базовым итератором, до начала этой последовательности. Фундаментальное соотношение между обратным итератором и его соответствующим итератор i устанавливается идентичностью: &*(reverse_iterator(i)) == &*(i - 1).
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); }
Кроме того,
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]).
constexpr reverse_iterator();
Effects: Значение инициализирует current. Операции итератора, применяемые к результирующему итератору, имеют определенное поведение тогда и только тогда, когда соответствующие операции определены в итераторе типа, инициализированном значением 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;
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);
Чтобы можно было обрабатывать вставку так же, как запись в массив,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 три функции , делающие вставки итераторы из контейнера.
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); }
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);
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); }
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);
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); }
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);
Шаблон класса 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 ]
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); }
Параметр шаблона Iterator должен соответствовать требованиям для input iterator. Кроме того, если реализуется какая-либо из функций обхода с двунаправленным или произвольным доступом, параметр шаблона должен соответствовать требованиям для a Bidirectional Iterator или a Random Access Iterator, соответственно.
constexpr move_iterator();
Effects: Создает объект move_iterator, инициализирующий значение current. Операции итератора, применяемые к результирующему итератору, имеют определенное поведение тогда и только тогда, когда соответствующие операции определены в итераторе типа, инициализированном значением 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 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;
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);
Чтобы алгоритмические шаблоны могли работать напрямую с потоками ввода / вывода, предоставляются соответствующие шаблоны классов, подобные итератору.
[ Example:
partial_sum(istream_iterator<double, char>(cin), istream_iterator<double, char>(), ostream_iterator<double, char>(cout, "\n"));
читает файл, содержащий числа с плавающей запятой cin, и печатает в нем частичные суммы cout. ] — end example
Шаблон класса 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); }
constexpr istream_iterator();
Effects: Создает итератор конца потока. Если is_trivially_default_constructible_v<T> есть true, то этот конструктор является конструктором constexpr.
istream_iterator(istream_type& s);
Effects: Инициализируется in_stream с помощью addressof(s). value может быть инициализирован во время построения или при первом обращении к нему.
istream_iterator(const istream_iterator& x) = default;
Effects: Создает копию x. Если is_trivially_copy_constructible_v<T> есть true, то этот конструктор является тривиальным конструктором копирования.
~istream_iterator() = default;
const T& operator*() const;
const T* operator->() const;
istream_iterator& operator++();
istream_iterator operator++(int);
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);
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 }; }
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);
Шаблон класса 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); }
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++). Он сохраняет символ, на который указывает предыдущее значение итератора для некоторого возможного доступа в будущем для получения символа.
Для каждого istreambuf_iterator конструктора в этом разделе итератор конца потока создается тогда и только тогда, когда член, sbuf_ предназначенный только для представления, инициализируется значением нулевого указателя.
constexpr istreambuf_iterator() noexcept;
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;
Returns: true тогда и только тогда, когда оба итератора находятся в конце потока или ни один из них не находится в конце потока, независимо от того, какой streambuf объект они используют.
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);
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 в выходной поток, из которого он был построен. Невозможно получить символьное значение из итератора вывода.
ostreambuf_iterator(ostream_type& s) noexcept;
ostreambuf_iterator(streambuf_type* s) noexcept;
ostreambuf_iterator& operator=(charT c);
Effects: Если failed() уступает false, звонит sbuf_->sputc(c); в противном случае не имеет никакого эффекта.
ostreambuf_iterator& operator*();
ostreambuf_iterator& operator++();
ostreambuf_iterator& operator++(int);
bool failed() const noexcept;
Помимо того , что доступны через включение <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());
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> заголовка, функциональные шаблоны [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());
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;