Please forgive me if this is a trivial question, I'm just learning C++ and try to wrap my head around certain concepts. Especially when it comes to iterators, I'm completely lost.
Say I have a custom class representing some data structure, and one of its members is a vector of integers. I want to write a bidirectional iterator for that class, which outputs only the EVEN numbers in the vector. Is there an easy and instructive way? I'd prefer not using libraries other than STL.
Not sure making your own iterator is easy. But probably the best is to use a conditional for_each
functions.
std::for_each
does an operation on every elements. It's pretty easy to create a for_each_if
doing an operation on some specific elements. For instance, program below only prints even numbers from the vector (4, 6 and 8).
#include <iostream>
#include <vector>
using namespace std;
struct is_even {
typedef bool return_type;
bool operator() (const int& value) {return (value%2)==0; }
};
struct doprint {
bool operator() (const int& value) { std::cout << value << std::endl; }
};
template <class InputIterator, class Predicate, class Function>
void for_each_if(InputIterator first, InputIterator last, Function f, Predicate pred)
{
while ( first != last )
{
if (pred (*first))
f(*first++);
else
first ++;
}
}
int main()
{
std::vector<int> v;
v.push_back( 4 );
v.push_back( 5 );
v.push_back( 6 );
v.push_back( 8 );
for_each_if( v.begin(), v.end(), doprint(), is_even());
return 0;
}
Going by your requirements, deriving from vector::iterator
would probably be the easiest:
class my_iterator : private std::vector<int>::iterator {
typedef std::vector<int>::iterator base;
base m_base_end; // Stores the real end iterator of the internal vector.
// We need it so that the even/odd checking code
// doesn't run off the end of the vector
// (initialize it in a constructor, omitted here for
// brevity).
public:
using base::operator*;
using base::operator->;
// etc. for other members...
// except for increment:
my_iterator& operator++()
{
do {
base::operator++();
} while( static_cast<base&>(*this) != m_base_end
&& base::operator*() % 2 );
return *this;
}
my_iterator operator++(int)
{
my_iterator temp;
operator++();
return temp;
}
// TODO: decrement and other arithmetic operators
};
It's still quite a bit of boilerplate, and you'll also want to do the same for const_iterator
(I'd probably make the above class a template to make it easier).
Consider Boost for this - it has filter_iterator
just for this purpose. There's also iterator_adaptor
if that doesn't suit you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With