Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why boost filter_iterator has weird make_filter_iterator function?

after some pain I managed to hack together this minimal example of boost 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;
}

It works nice, but I wonder why the make_filter_iterator takes numbers.end()? I might be wrong to use it that way, I guestimated it from the C array example:
http://www.boost.org/doc/libs/1_53_0/libs/iterator/example/filter_iterator_example.cpp

like image 301
NoSenseEtAl Avatar asked Jan 14 '23 21:01

NoSenseEtAl


1 Answers

That is explained in the docs:

When skipping over elements, it is necessary for the filter adaptor to know when to stop so as to avoid going past the end of the underlying range. A filter iterator is therefore constructed with pair of iterators indicating the range of elements in the unfiltered sequence to be traversed.

From the source below you can see the always check 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());
}

Also, as pointed out by Alex Chamberlain, the constructors make it optional when passing the end iterator, for example: filter_iterator(Iterator x, Iterator end = Iterator()); (provided it is default constructible). So, you could omit numbers.end() from your code when constructing the end iterator.

like image 61
Jesse Good Avatar answered Jan 29 '23 11:01

Jesse Good