Ответ 1
Почти; компилятор будет искать в нескольких других местах начальный и конечный итераторы, если он не сможет найти методы begin
или end
в классе контейнера; так работают циклы на основе диапазона для массивов, которые не имеют членов begin
и end
. Он также будет искать бесплатные функции begin
и end
от ADL, и, в конечном итоге, std::begin
и std::end
, так что есть много возможностей для модификации на основе диапазона для поддержки петель для существующих контейнеров. Раздел 6.5.4 содержит подробности.
На ваш другой вопрос, итераторы абсолютно могут быть ленивыми! Хорошим примером является std::istream_iterator
, который должен быть ленивым, поскольку он читает ввод с консоли.
Требование использовать итератор в цикле for
состоит в том, что он должен удовлетворять категории входных итераторов, что описано в разделе 24.2.3; для этой категории необходимы следующие операции: !=
, унарный *
, pre- и постинкрементное ++
.
Чтобы сообщить языку, что вы создали входной итератор, вы должны наследовать от std::iterator<std::input_iterator_tag, T, void, T *, T &>
, где T
- это тип, с которым работает ваш итератор (раздел 24.4.3).