Why does boost filterer have a weird make_filter_iterator function?

after some pain I managed to crack this minimal boost filter_iterator example.

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; } 

This works well, but I wonder why make_filter_iterator accepts numbers.end() ? Maybe I'm wrong to use it this way, I invited it from an example C array:
http://www.boost.org/doc/libs/1_53_0/libs/iterator/example/filter_iterator_example.cpp

+4
source share
2 answers

This is explained in the docs :

When skipping items, it is necessary that the filter adapter know when to stop so as not to get past the end of the assortment. Therefore, a filter iterator is built with a pair of iterators indicating the range of elements in an unfiltered sequence to pass through.

From the source below, you can see that it always checks to see if they have reached the end in 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()); } 

In addition, as Alex Chamberlain noted, designers do this optionally when passing the final iterator, for example: filter_iterator(Iterator x, Iterator end = Iterator()); (provided that it is constructive by default). That way, you can omit numbers.end() from your code when building the final iterator.

+8
source

If you look at the declaration of your make_filter_iterator template, you will see that it looks like this:

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

In particular, you see that the last parameter is the default parameter, and it is set to Iterator() , which means its standard change, and for some types of iterators, it behaves like an actual iterator end() , which indicates any array one after the other , i.e. indicates garbage.

Most container types require passing the actual end() iterator.

+1
source

All Articles