//***************************************************************************
//* Copyright (c) 2015 Saint Petersburg State University
//* Copyright (c) 2011-2014 Saint Petersburg Academic University
//* All Rights Reserved
//* See file LICENSE for details.
//***************************************************************************

#ifndef FILTER_ITERATOR_H_
#define FILTER_ITERATOR_H_

/**
 * Iterator with some predicate -- iterates only on elements with predicate(item) == true
 */
template<typename iterator_type, typename predicate_type>
class filter_iterator {
public:
	typedef typename iterator_type::value_type value_type;

	filter_iterator(const iterator_type& begin, const iterator_type& end, const predicate_type& pred):
		current_(begin), end_(end), pred_(pred)
	{
		while((current_ != end_) && (!pred_(*current_))) // why do we need here? DRY, see method advance() below.
			++current_;
	} // filter_iterator

	value_type operator*() const { return *current_; }
	value_type operator->() const { return *current_; }

	filter_iterator& operator++() { advance(); return *this; }

	bool operator==(const filter_iterator& rhs) const { return current_ == rhs.current_; }
	bool operator!=(const filter_iterator& rhs) const { return !(operator==(rhs)); }

private:
	void advance()
	{
		do
		{
			++current_;
		}
		while((current_ != end_) && (!pred_(*current_)));
	} // advance

	iterator_type current_;
	iterator_type end_;
	predicate_type pred_;
};

#endif /* FILTER_ITERATOR_H_ */
