Вход на сайт
Abstrakter Iterator из области С++
04.07.12 16:10
Последний раз изменено 04.07.12 16:12 (evgher)
Слудующая проблема
Изначально создаю обобщающий итератор, который определяет методы:\
Также создаю специализированный итератор
при компиляции выходит сообщение
Как можно это заставить работать?
Изначально создаю обобщающий итератор, который определяет методы:\
В ответ на:
class AbstractIter{
public:
// constructor
AbstractIter(Element *pC);
bool operator!=(AbstractIter &ri);
Entry& operator*() ;
virtual AbstractIter& operator++( ) = 0; //prefix
virtual AbstractIter operator++(int) = 0; //postfix
class AbstractIter{
public:
// constructor
AbstractIter(Element *pC);
bool operator!=(AbstractIter &ri);
Entry& operator*() ;
virtual AbstractIter& operator++( ) = 0; //prefix
virtual AbstractIter operator++(int) = 0; //postfix
Также создаю специализированный итератор
В ответ на:
class PostOrderIter : public AbstractIter{
public:
PostOrderIter();
virtual AbstractIter& operator++() ;
virtual AbstractIter operator++(int);
};
class PostOrderIter : public AbstractIter{
public:
PostOrderIter();
virtual AbstractIter& operator++() ;
virtual AbstractIter operator++(int);
};
при компиляции выходит сообщение
В ответ на:
Error: Cannot return a value of abstract class BinTree<int>::AbstractIter.
Where: While instantiating "BinTree<int>::PostOrderIter::operator++(int)".
Error: Cannot return a value of abstract class BinTree<int>::AbstractIter.
Where: While instantiating "BinTree<int>::PostOrderIter::operator++(int)".
Как можно это заставить работать?
NEW 04.07.12 17:47
в ответ evgher 04.07.12 16:10
Вообще то итераторы предполагают использование template( хотя бы по Вашему типу Еntry), a шаблоны с virtual не дружат. Если хотите - делайте специализацию шаблонов, virtual тут не при чем.
А если хотите дальше заниматься глупостью, ибо иначе написанное выше назвать трудно, operator++(int) должен возвращать ссылку на объект, так что добавьте &, и будет Вам щастье:):)
А если хотите дальше заниматься глупостью, ибо иначе написанное выше назвать трудно, operator++(int) должен возвращать ссылку на объект, так что добавьте &, и будет Вам щастье:):)
NEW 04.07.12 18:09
Я тут с Вами не очень согласен. У постфикс-оператора это просто не возможно. Он возвращает копию объекта. Смотрите ниже пример из инета.
В ответ на:
operator++(int) должен возвращать ссылку на объект
operator++(int) должен возвращать ссылку на объект
Я тут с Вами не очень согласен. У постфикс-оператора это просто не возможно. Он возвращает копию объекта. Смотрите ниже пример из инета.
В ответ на:
Number& Number::operator++ ()
{
...
return *this;
}
Number Number::operator++ (int)
{
Number ans = *this;
++(*this); // or just call operator++()
return ans;
}
Number& Number::operator++ ()
{
...
return *this;
}
Number Number::operator++ (int)
{
Number ans = *this;
++(*this); // or just call operator++()
return ans;
}
NEW 04.07.12 18:19
Дело в том что идея состоит в том траверзировать контейнер с помощью разных итераторов в основу обобщающего итератора (абстрактного).
Т. е. все классы итераторы (специализированные или нет) это внутренние классы контейнера.
Самая главная проблема наверное и состоит в использовании template и virtual. Если использовать похожиую конструкцию без template, то всё вполне вероятно зароботает.
Но меня интересует именно тот факт - возможно это или нет.
в ответ ThorV 04.07.12 17:47
В ответ на:
Вообще то итераторы предполагают использование template( хотя бы по Вашему типу Еntry), a шаблоны с virtual не дружат. Если хотите - делайте специализацию шаблонов, virtual тут не при чем.
Вообще то итераторы предполагают использование template( хотя бы по Вашему типу Еntry), a шаблоны с virtual не дружат. Если хотите - делайте специализацию шаблонов, virtual тут не при чем.
Дело в том что идея состоит в том траверзировать контейнер с помощью разных итераторов в основу обобщающего итератора (абстрактного).
Т. е. все классы итераторы (специализированные или нет) это внутренние классы контейнера.
Самая главная проблема наверное и состоит в использовании template и virtual. Если использовать похожиую конструкцию без template, то всё вполне вероятно зароботает.
Но меня интересует именно тот факт - возможно это или нет.
NEW 06.07.12 07:00
в ответ evgher 04.07.12 22:25
Не вполне. Курить здесь - http://www.boost.org/doc/libs/1_50_0/libs/iterator/doc/index.html
А вообще главное умение для программиста - умение гуглить. Например так: https://www.google.com/search?hl=en&q=c%2B%2B+iterator+site%3Astackoverflow.com
А вообще главное умение для программиста - умение гуглить. Например так: https://www.google.com/search?hl=en&q=c%2B%2B+iterator+site%3Astackoverflow.com
NEW 06.07.12 10:42
Что-то говорит мне, что итераторы с шаблонами никак не связаны :) Просто потому что шаблон нужен для более высокого уровня абстракции, а итератор для перебора элементов.
Так например FindFirstFile и FindNextFile - вполне себе итератор, но шаблонами там и не пахнет :)
Очевидно, что реалицовывать итератор можно и без шаблонов. Например:
как видишь, итератор есть, а шаблонов нет :)
в ответ ThorV 04.07.12 21:50
В ответ на:
Самое главное - итераторы реализуются шаблонами, иногда их специализируют, но не виртуальными классами.
Самое главное - итераторы реализуются шаблонами, иногда их специализируют, но не виртуальными классами.
Что-то говорит мне, что итераторы с шаблонами никак не связаны :) Просто потому что шаблон нужен для более высокого уровня абстракции, а итератор для перебора элементов.
Так например FindFirstFile и FindNextFile - вполне себе итератор, но шаблонами там и не пахнет :)
Очевидно, что реалицовывать итератор можно и без шаблонов. Например:
В ответ на:
class IIterator
{
public:
virtual void * Prev () = 0;
virtual void * Next () = 0;
virtual void * Value () = 0;
}
class CList : public IIterator
{
}
class IIterator
{
public:
virtual void * Prev () = 0;
virtual void * Next () = 0;
virtual void * Value () = 0;
}
class CList : public IIterator
{
}
как видишь, итератор есть, а шаблонов нет :)
NEW 07.07.12 08:40
в ответ Программист 06.07.12 10:42
По поводу FindxxxFile рассмешил. Специализированная операция прохода по списку и итератор. Ню ню. А как без шаблонов реализовать универсальный итератор на c++, чтоб им можно было дереференсировать любые объекты, поделись пожалуйста опытом. reinterpret_cast<MySuperPuperClass>( void* ) рулит?
NEW 08.07.12 13:34
в ответ ThorV 07.07.12 08:15
Задача итетатора - пройти по элементам списка.
Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Кроме того, шаблонами хорошо описывать алгоритмы без привязки к типам данных, однако при использовании шаблонов ты все равно должен задать тип данных. Стл-список на void * накойже валинный как и на любом другом типе данных. А если у тебя есть структура классов, то ты легко можешь реализовать итератор на этих классах БЕЗ использования шаблонов.
Я не говорю о том насколько это хорошо или плохо (зачем изобретать велосипед, когда есть стл? :D), но все таки итераторы (по своему смыслу) вполне себе могут существовать и без шаблонов.
В ответ на:
Ню ню. А как без шаблонов реализовать универсальный итератор на c++, чтоб им можно было дереференсировать любые объекты, поделись пожалуйста опытом. reinterpret_cast<MySuperPuperClass>( void* ) рулит?
Ню ню. А как без шаблонов реализовать универсальный итератор на c++, чтоб им можно было дереференсировать любые объекты, поделись пожалуйста опытом. reinterpret_cast<MySuperPuperClass>( void* ) рулит?
Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Кроме того, шаблонами хорошо описывать алгоритмы без привязки к типам данных, однако при использовании шаблонов ты все равно должен задать тип данных. Стл-список на void * накойже валинный как и на любом другом типе данных. А если у тебя есть структура классов, то ты легко можешь реализовать итератор на этих классах БЕЗ использования шаблонов.
Я не говорю о том насколько это хорошо или плохо (зачем изобретать велосипед, когда есть стл? :D), но все таки итераторы (по своему смыслу) вполне себе могут существовать и без шаблонов.
NEW 08.07.12 19:30
return this; там стоит. Это конечно дебилизм - приравнивать контейнер к итератору, но инстанция там есть.
Это было очевидно Абрахамсу уже 10 лет назад, почему он и написал итератор адаптор. На который я выше давал ссылку.
в ответ Murr 08.07.12 17:19
В ответ на:
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...
return this; там стоит. Это конечно дебилизм - приравнивать контейнер к итератору, но инстанция там есть.
В ответ на:
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...
Это было очевидно Абрахамсу уже 10 лет назад, почему он и написал итератор адаптор. На который я выше давал ссылку.
NEW 08.07.12 20:17
в ответ scorpi_ 08.07.12 19:30
return this; там стоит.
------
Это Я вижу.
Я не вижу имплементации абстрактных методов. Писать их нет желания, а без них этот this бессмысленнен.
я выше давал ссылку
-----
Это не совсем ко мне - это к изобретателям сложных имплементаций давно наработанных решений.
------
Это Я вижу.
Я не вижу имплементации абстрактных методов. Писать их нет желания, а без них этот this бессмысленнен.
я выше давал ссылку
-----
Это не совсем ко мне - это к изобретателям сложных имплементаций давно наработанных решений.
NEW 08.07.12 21:23
в ответ Программист 08.07.12 13:34
>>Задача итетатора - пройти по элементам списка.
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив

>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет

>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?
NEW 08.07.12 22:30
Универсальность чаще всего идет в конфликте с производительностью или требуемым рессурсам.
Наоборот: каждому контейнеру свой итератор - специализированыый и быстрый и наиболее лучше подходящий.
Ну разве то ради забавы да спортивного интереса...
в ответ ThorV 08.07.12 21:23
В ответ на:
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
мне лично совершенно не понятно ЗАЧЕМ нужна такая вот универсальность?Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
Универсальность чаще всего идет в конфликте с производительностью или требуемым рессурсам.
Наоборот: каждому контейнеру свой итератор - специализированыый и быстрый и наиболее лучше подходящий.
Ну разве то ради забавы да спортивного интереса...

Проклят нарушающий межи ближнего своего (Втор.27:17)
NEW 09.07.12 00:40
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
в ответ ThorV 08.07.12 23:45
В ответ на:
на кой тогда нужны итераторы вообще?
а чем итерировать без них то?на кой тогда нужны итераторы вообще?
В ответ на:
Интерфейс итераторов STL и с++-98 абсолютно универсален
как раз там несколько специализированных итераторов для разных контейнеров.Интерфейс итераторов STL и с++-98 абсолютно универсален
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
Проклят нарушающий межи ближнего своего (Втор.27:17)
NEW 09.07.12 01:26
Ну да, лучше как в жабе, где список возвращает итератор случайного доступа...
в ответ anly 09.07.12 00:40
В ответ на:
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
Ну да, лучше как в жабе, где список возвращает итератор случайного доступа...

NEW 09.07.12 07:55
Вы наверное имели ввиду operator++.
'Мгновенная' реализация, т.е. О(1), заслуга вовсе не итератора, а структуры данных, выбранной для реализации вектора.
Советую немного почитать про STL.
в ответ anly 09.07.12 00:40
В ответ на:
как раз там несколько специализированных итераторов для разных контейнеров.
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
как раз там несколько специализированных итераторов для разных контейнеров.
к примеру vector::iterator имеет operator+=(int N), и реализация его считай мгновенная
а list::iterator такового не имеет, в виду того что реализовать его мгновенно (т.е. без перебора N раз) невозможно.
Вы наверное имели ввиду operator++.
'Мгновенная' реализация, т.е. О(1), заслуга вовсе не итератора, а структуры данных, выбранной для реализации вектора.
Советую немного почитать про STL.
NEW 09.07.12 10:45
Ты уж прости меня, но писать всю эту требуху я не буду :) Ибо не смысла :D
кэп! :)
в ответ Murr 08.07.12 17:19
В ответ на:
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...
Чего Я не вижу - где инстанцируется то, что должно быть возвращено...
Ты уж прости меня, но писать всю эту требуху я не буду :) Ибо не смысла :D
В ответ на:
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...
Ну и, должно быть очевидно, что писать руками имплементацию итератора каждый раз нет никакого желания...
кэп! :)
NEW 09.07.12 10:58
Задача (прикладная) пройтись по элементам конкретного контейнера, о котором известно ВСЕ уже на стадии написания кода.
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.
Ну так можно ж сделать виртуальную функцию... в чем проблема?
Ты что пытаешься мне доказать? Что стл рулит? :) Я это и так знаю и использую стл когда мне это нужно :) И своих итераторов не пишу :)
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?
в ответ ThorV 08.07.12 21:23
В ответ на:
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
Задача (прикладная) пройтись по элементам конкретного контейнера, о котором известно ВСЕ уже на стадии написания кода.
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.
В ответ на:
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
Ну так можно ж сделать виртуальную функцию... в чем проблема?
В ответ на:
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы?
Ты что пытаешься мне доказать? Что стл рулит? :) Я это и так знаю и использую стл когда мне это нужно :) И своих итераторов не пишу :)
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?
NEW 09.07.12 11:32
А как поступим с примитивными типами данных?
Конечно можно. Но только в качестве примера, типа так делать ни в коем случае нинада :-)
в ответ Программист 09.07.12 10:58
В ответ на:
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.
А "пройтись по ЛЮБОМУ" контейнеру - это АБСТРАКЦИЯ, и разрешается, например, шаблонами. А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject. Итератор будет, а шаблонов нет.
А как поступим с примитивными типами данных?
В ответ на:
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?
Но ведь это не означает, что нельзя написать итератор БЕЗ шаблона? Или как?
Конечно можно. Но только в качестве примера, типа так делать ни в коем случае нинада :-)
NEW 09.07.12 12:09
Уверен, что для примитивов тожно можено накалякать итератор :)
Ну вот и славненько :)
Следовательно высказывание
опровергнуто.
ЧТД.
Это уже другая тема :D
в ответ abubakr 09.07.12 11:32
В ответ на:
А как поступим с примитивными типами данных?
А как поступим с примитивными типами данных?
Уверен, что для примитивов тожно можено накалякать итератор :)
В ответ на:
Конечно можно.
Конечно можно.
Ну вот и славненько :)
Следовательно высказывание
В ответ на:
Вообще то итераторы предполагают использование template
Вообще то итераторы предполагают использование template
опровергнуто.
ЧТД.
В ответ на:
Но только в качестве примера, типа так делать ни в коем случае нинада :-)
Но только в качестве примера, типа так делать ни в коем случае нинада :-)
Это уже другая тема :D
NEW 09.07.12 18:02
>>Задача (прикладная) пройтись по элементам конкретного контейнера, о котором известно ВСЕ уже на стадии написания кода.
Да ну? А как же быть с std::copy и практически всем <algorithm>?
>>Ну так можно ж сделать виртуальную функцию... в чем проблема?
Ни в чем, но зачем ? Ради dynamic_cast'а? Кстати, если ты уж озабочен производительностью, то dynamic_cast вещь довольно тяжеловесная, я уж не говорю, что :(
>>А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject.
Привет из жабы... Осталось только как в жабе написать классы-оболочки вокруг встроенных типов( по другому и не получится )...
Самое главное, то что вы вдвоем впариваете, в лучшем случае может ( через анус и тухес ) работать со списками и деревьями, но пока что я не услышал ответа на вопрос: как итератор, не заточенный под конкретный тип дереференцируемого объекта, можно без шаблонов реализовать для векторов и массивов?
Короче, резюме:
Ты мне хочешь доказать, что умеешь ковырять в носу пяткой? Можно и так, согласен, но не надо пропагандировать это как здоровый образ жизни.
Да ну? А как же быть с std::copy и практически всем <algorithm>?
>>Ну так можно ж сделать виртуальную функцию... в чем проблема?
Ни в чем, но зачем ? Ради dynamic_cast'а? Кстати, если ты уж озабочен производительностью, то dynamic_cast вещь довольно тяжеловесная, я уж не говорю, что :(
>>А можно эту абвстракцию разрешить и другим способом - например унаследовав все типы данных от CObject.
Привет из жабы... Осталось только как в жабе написать классы-оболочки вокруг встроенных типов( по другому и не получится )...
Самое главное, то что вы вдвоем впариваете, в лучшем случае может ( через анус и тухес ) работать со списками и деревьями, но пока что я не услышал ответа на вопрос: как итератор, не заточенный под конкретный тип дереференцируемого объекта, можно без шаблонов реализовать для векторов и массивов?
Короче, резюме:
Ты мне хочешь доказать, что умеешь ковырять в носу пяткой? Можно и так, согласен, но не надо пропагандировать это как здоровый образ жизни.
NEW 31.07.12 16:36
Это где вы такое определение видели? Вики говорит: "an iterator is an object that enables a programmer to traverse a container. "
Хотите задачу "из жизни". Есть контейнер, реализованный то ли как вектор, то ли лист. Он содержит пойнтеры на абстрактный CChannel, из который наследуется DVB-S Channel, DVB-T Channel, DVB-C Channel, etc (спутник, наземный сигнал, кабель, и т.д.)
По этому листу надо пройтись огромной кучей способов: последовательно от одного к другому, последовательно но пропустить не совпадающие каналы (для DVB-S должны совпадать bandwidth и поляризация - не суть важно), перепрыгнуть на величину графической страницы, перепрыгнуть но только на совпадающий канал, и т.д.
В этой задаче то, что предложил ТС и то что поддерживает "Программист" это то, что и нужно и ты не обойдешся здесь решениями из STL, и ни кто здесь не говорит об универсальном итераторе для встроенных типов, то есть "каждому овощу - свою корзину!"
В ответ на:
>>Задача итетатора - пройти по элементам списка.
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
>>Задача итетатора - пройти по элементам списка.
Задача итератора - пройтись по ЛЮБОМУ контейнеру, включая вектор и массив
Это где вы такое определение видели? Вики говорит: "an iterator is an object that enables a programmer to traverse a container. "
В ответ на:
>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?
>>Ну тогда уж dinamic_cast, чтобы проверить на NULL :D
А если у класса нет виртуальных функций, то компилятор шлет такому dynamic_cast большой пианэрский привет
>>В любом случае, если не хочешь иметь дело с void *, то используй структуру классов. В чем проблема?
Извини конечно, но какого ...уя использовать малопривлекательное решение от Явы? Как быть со встроенными типами? Писать оболочки вокруг int/char/float?
Хотите задачу "из жизни". Есть контейнер, реализованный то ли как вектор, то ли лист. Он содержит пойнтеры на абстрактный CChannel, из который наследуется DVB-S Channel, DVB-T Channel, DVB-C Channel, etc (спутник, наземный сигнал, кабель, и т.д.)
По этому листу надо пройтись огромной кучей способов: последовательно от одного к другому, последовательно но пропустить не совпадающие каналы (для DVB-S должны совпадать bandwidth и поляризация - не суть важно), перепрыгнуть на величину графической страницы, перепрыгнуть но только на совпадающий канал, и т.д.
В этой задаче то, что предложил ТС и то что поддерживает "Программист" это то, что и нужно и ты не обойдешся здесь решениями из STL, и ни кто здесь не говорит об универсальном итераторе для встроенных типов, то есть "каждому овощу - свою корзину!"
NEW 31.07.12 17:17
в ответ Simple 31.07.12 16:49
А никто и не говорит об конкретных типах: CChannel имеет какои нибудь bool IsCompatibly( CChannel& ) =0. Только второй итератор должен пропускать, те элементы которые ответят false, а первый итератор об этом и не спрашивает. А четверый ещё и должен подсчитывать, а сколько элементов он не пропустил.