Пример итератора ввода, где `end ()` на самом деле означает «один за концом»?

В настоящее время я пытаюсь понять некоторые идеи WRT. C ++ итераторы, и мне было интересно …

Учитывая Инкрементальный / однопроходный / Итератор ввода / вывода, может ли на самом деле существовать такая вещь, как позиция / элемент «один за другим» для такого Итератора, или все они InputIterator end() Итераторы «естественно» представляют собой некоторую форму сингулярных значений, которые специально обрабатываются operator==?

Я думаю, что я имею в виду это: ForwardIterator на «вверх», может иметь смысл иметь тривиальный operator== который просто проверяет, являются ли два объекта итератора, независимо от end-несс, указывают на один и тот же элемент. Может ли это иметь смысл для InputIterator?

1

Решение

InputIterator это не ForwardIterator это тот, для которого его увеличение делает недействительным предыдущее значение (имеется в виду любой итератор с таким же значением, то есть любые копии оригинала).

В общем случае допустимо сравнивать итераторы из «одной и той же последовательности» (то есть, когда один достижим из другого). Для итераторов, о которых вы говорите, это означает, что единственные допустимые сравнения:

  • два равных не конечных итератора
  • два конечных итератора
  • конечный итератор и неконечный итератор

Вы не можете (по гарантиям этого интерфейса) сравнить два неравных не конечных итератора, потому что у вас никогда не будет двух допустимых не конечных итераторов, где один доступен из другого. Тот, который «позади», уже признан недействительным.

Так что, вероятно, вы мог реализовать итератор таким образом, чтобы он содержал элемент данных, который имеет одно значение в конечных итераторах и другое значение в не конечных итераторах. Для типичного примера потокового итератора этот элемент данных может быть bool isEndOfStream, затем operator== не нужно содержать какой-либо особый код, просто нужно сравнить это поле. Тогда было бы естественно, чтобы все конечные итераторы были взаимозаменяемыми: это поле — единственное, что на них когда-либо будет использоваться.

Это может быть эффективно, так как итераторы становятся конечными итераторами гораздо реже, чем сравниваются итераторы, так что запись в редком случае, чтобы обычным случаем было просто чтение и сравнение, показалась бы разумной. Такое сравнение итераторов вернуло бы true для любых двух не конечных итераторов, но это нормально, потому что либо они действительно равны (в этом случае возвращение true является правильным), либо сравнение их недопустимо (в этом случае поведение не определено).

2

Другие решения

Каноническим примером является istream_iterator (шаблон), который становится единичным, когда не удается извлечь основной поток. Это можно обнаружить путем сравнения с созданным по умолчанию итератором того же типа, что эквивалентно единственному итератору. Например:

std::vector<int> v(std::istream_iterator<int>(std::cin), {});

Это эквивалент:

std::vector<int> v;
for (int n; std::cin >> n; ) { v.push_back(n); }

Подчеркнем еще раз: все итераторы istream «один за другим» эквивалентны, независимо от потока, из которого они вышли. Эти итераторы являются примером, где «единственное число» (= не связано с каким-либо контейнером) и «один за другим» (= результат увеличения последнего разыменованного итератора) означают одно и то же.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector