// file:          SearcharrayGeneral.hpp
// description:   Combination of SearchspaceGeneral and OwnerOfArray.
//                Sak A16(4, 8), Sak P52, PÜ 31.5(13)(d, h).
// author:        Karlheinz Hug
// creation date: 2012-06-18
// last update:   2012-07-02

#ifndef SEARCHARRAY_GENERAL_HPP_
#define SEARCHARRAY_GENERAL_HPP_

#include <algorithm>

#include "SearchspaceGeneral.hpp"
#include "OwnerOfArray.hpp"

	template <typename T>
	class SearcharrayGeneral : public virtual SearchspaceGeneral<T>, protected OwnerOfArray<T>
	{
		public:
			virtual void fill (unsigned int size, T min_item, T max_item);

			virtual void for_all_act (void (*act) (T x));

			const static int not_found = -1;
				// invariant: value never used as array index: not_found < low.

			virtual int some_index (T x);
				// Some position of x in the array, if any, else not_found.
				// Template method using services of protected part.
				// Final! Normally, do not override!

		protected:
			virtual int position (T x) = 0;
				// precondition: done(x)
				// postcondition: result != not_found implies array[result] == x.
	}; // SearcharrayGeneral

	template <typename T>
	void SearcharrayGeneral<T>::fill (unsigned int size, T min_item, T max_item)
	{
		init_array(size, min_item, max_item);
	}

	template <typename T>
	void SearcharrayGeneral<T>::for_all_act (void (*act) (T x))
	{
		// Index variant:
		//	for (unsigned int index = 0; index < this->array.size(); ++index)
		//	{
		//		act(this->array[index]);
		//	}

		// Iterator variant:
		//  typename std::vector<T>::iterator pos;
		//  for (pos = this->array.begin(); pos != this->array.end(); ++pos)
		//  {
		//  	act(*pos);
		//  }

		// Algorithm variant:
		for_each(this->array.begin(), this->array.end(), act);
			// 'this' necessary because for_all_act, array from different base classes.
	}

	template <typename T>
	int SearcharrayGeneral<T>::some_index (T x)
	{
		init(x);
		loop_invariants(x);
		while (!done(x))
		{
			reduce(x);
			loop_invariants(x);
		};
		return position(x);
	}

#endif // SEARCHARRAY_GENERAL_HPP_
