Почему boost filter_iterator имеет странную функцию make_filter_iterator?

после некоторой боли мне удалось взломать этот минимальный пример повышения filter_iterator

using namespace std;
std::function<bool(uint32_t)> stlfunc= [](uint32_t n){return n%3==0;};
int main()
{
vector<uint32_t> numbers{11,22,33,44,55,66,77,3,6,9};
auto start = boost::make_filter_iterator(stlfunc, numbers.begin(), numbers.end());
auto end   = boost::make_filter_iterator(stlfunc, numbers.end()  , numbers.end());
auto elem  = std::max_element(start,end);
cout << *elem;
}

Это хорошо работает, но мне интересно, почему make_filter_iterator принимает numbers.end()?
Я могу ошибаться, если использую его таким образом, я предположил это на примере массива C:
http://www.boost.org/doc/libs/1_53_0/libs/iterator/example/filter_iterator_example.cpp

4

Решение

Это объясняется в документы:

При пропуске элементов необходимо, чтобы адаптер фильтра
знать, когда остановиться, чтобы не пройти через конец основного
спектр. Поэтому итератор фильтра создается с парой
итераторы, указывающие диапазон элементов в нефильтрованной последовательности
быть пройденным.

Из источника ниже вы можете увидеть, всегда ли они достигли конца в satisfy_predicate:

void increment()
{
++(this->base_reference());
satisfy_predicate();
}

void satisfy_predicate()
{
while (this->base() != this->m_end && !this->m_predicate(*this->base()))
++(this->base_reference());
}

Кроме того, как указано Алекс Чемберлен,
конструкторы делают его необязательным при прохождении конечного итератора, например: filter_iterator(Iterator x, Iterator end = Iterator()); (при условии, что это значение по умолчанию). Таким образом, вы могли бы опустить numbers.end() из вашего кода при создании конечного итератора.

8

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

Если вы посмотрите на декларацию вашего make_filter_iterator шаблон, вы видите, это выглядит так:

template <class Predicate, class Iterator>
filter_iterator<Predicate,Iterator>
make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

В частности, вы видите, что последний параметр является параметром по умолчанию, и он установлен в Iterator() что означало бы, что это по умолчанию и для некоторые типы итератора он ведет себя как фактический end() итератор, который указывает один конец конца любого массива, то есть указывает на мусор.

Большинство типов контейнеров требуют фактического end() итератор для передачи.

1