/* Lecture code 10.1
 *
 * Implementation of Copy and CopyIf using template functions.
 */

#include <iostream>
#include <vector>
using namespace std;

/* Copies elements in the range [start, stop) to the range starting at
 * where.  Notice that this is parameterized over two types - InputIterator,
 * the type of the iterators start and stop, and OutputIterator, the type of
 * the iterator where.  Calling this function with any valid iterators will
 * compile, and otherwise will cause a compiler error where some invalid
 * operation was applied to the parameter.
 *
 * Technically speaking this function should probably return the iterator
 * one past the last spot we've written to (in accordance with STL convention),
 * but it's not strictly necessary to do so.
 */
template <typename InputIterator, typename OutputIterator>
void Copy(InputIterator start, InputIterator stop, OutputIterator where)
{
	/* Iterate from start to stop, copying into where and incrementing both
	 * the start and where iterators.
	 */
	for(; start != stop; ++start, ++where)
		*where = *start;
}

/* CopyIf is like Copy except that it only copies elements that pass some
 * particular predicate condition.  Note the addition of a Predicate
 * template argument and function parameter that lets us take in a Predicate
 * of any type we'd like.
 */
template <typename InputIterator, typename OutputIterator, typename Predicate>
void CopyIf(InputIterator start, InputIterator stop, OutputIterator where,
		    Predicate pred)
{
	/* Iterate from start to stop, checking if the current element passes the
	 * predicate and writing it to the output range if so.
	 */
	for(; start != stop; ++start)
	{
		if(pred(*start))
		{
			*where = *start;
			++where;
		}
	}
}

/* Code demonstrating CopyIf. */
const int kNumInts = 10;

bool IsEven(int value)
{
	return value % 2 == 0;
}

int main()
{
	vector<int> myVector;
	for(int i = 0; i < kNumInts; ++i)
		myVector.push_back(i);

	/* Print only even integers. */
	CopyIf(myVector.begin(), myVector.end(),
		   ostream_iterator<int>(cout, "\n"), IsEven);
}