6. Компиляция этого кода приведет к следующему сообщению об ошибке (рис. 3.3). Вы увидите ошибку, связанную с std::iterator_traits
7. Для исправления ситуации активизируем возможности типажей итераторов для нашего класса итератора. Сразу после определения num_iterator
std::iterator_traits
. Она сообщает STL, что наш итератор num_iterator является однонаправленным и итерирует по целочисленным значениям:namespace std {
template <>
struct iterator_traits
using iterator_category = std::forward_iterator_tag;
using value_type = int;
};
}
8. Скомпилируем код снова; мы видим, что он работает! Результат работы функций min/max выглядит следующим образом:
100 — 109
Как это работает
Одним алгоритмам STL нужно знать характеристики типа итератора, применяемого вместе с ними, другим — тип элементов, среди которых выполняется перебор. От этого зависят варианты реализации алгоритмов.
Однако все алгоритмы STL будут получать эту информацию о типе с помощью std::iterator_traits
my_iterator
. Этот класс типажа содержит до пяти разных определений членов.□ difference_type
it1 — it2
?□ value_type
*it
(обратите внимание: для чистых итераторов вывода этот тип будет void
)?□ pointer
□ reference
□ iterator_category:
Определения типов pointer
reference
и difference_type
не нужны для нашего итератора num_iterator
, поскольку он не итерирует по реальным значениям int
, но они не доступны на постоянной основе, как это было бы в случае использования массива). Поэтому лучше не определять их, поскольку если алгоритм зависит от доступности элементов диапазона в памяти, то при работе с нашим итератором он может генерировать Дополнительная информация
До появления C++17 поощрялось наследование итераторами типа std::iterator<...>
Используем оболочки итераторов для заполнения обобщенных структур данных
Часто требуется заполнить некий контейнер большим количеством данных, но источник данных и контейнер
Задачу по перемещению данных между концептуально разными структурами можно решить с помощью одной строки кода благодаря абстракциям, предоставляемым
Как это делается
В этом примере мы используем оболочки для итераторов, просто чтобы продемонстрировать их наличие и способы, которые могут помочь в решении часто встречающихся задач.
1. Сначала включим необходимые заголовочные файлы.
#include
#include
#include
#include
#include
2. Объявим об использовании пространства имен std
using namespace std;
3. Начнем с итератора std::istream_iterator
int
. Таким образом, он станет преобразовывать данные из стандартного потока ввода в целые числа. Например, при итерировании по нему он будет выглядеть так, будто имеет тип std::vector
. Конечный итератор имеет тот же тип, но не принимает аргументы конструктора.int main()
{
istream_iterator
istream_iterator