//
// C++ Interface: extalgorithm
//
// Description: 
//
//
// Author: Benjamin Mesing <bensmail@gmx.net>, (C) 2004
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef __EXTALGORITHM_2004_06_22
#define __EXTALGORITHM_2004_06_22

#include <algorithm>
#include <functional>

namespace NExtStd
{

 /**
	*  @brief Apply a function to every element of a sequence.
	*  @param  __first  An input iterator.
	*  @param  __last   An input iterator.
	*  @param  __f      A unary method function object.
	*  @param o  the class the method should be called for
	*  @return   @p f.
	*
	*  Applies the function object @p f to each element in the range
	*  @p [first,last).  @p f must not modify the order of the sequence.
	*  If @p f has a return value it is ignored.
	* @note this function is based on the GNU libcpp foreach function. 
	*/
template<typename _InputIter, typename _Function, typename Object>
_Function
for_each_ref(_InputIter __first, _InputIter __last, _Function __f, Object& o)
{
	// concept requirements
//	__glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
	for ( ; __first != __last; ++__first)
		(o.*__f)(*__first);
	return __f;
}

template<typename _InputIter, typename _Function, typename Object>
_Function
for_each(_InputIter __first, _InputIter __last, _Function __f, Object* o)
{
	// concept requirements
//	__glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
	for ( ; __first != __last; ++__first)
		(o->*__f)(*__first);
	return __f;
}


/** Copy algorithm as taken from Stroustrup2000 (Fourth Edition) page 566 (german translation)
  */
template <class In, class Out, class Pred>
Out copy_if(In anf, In end, Out res, Pred p)
{
	while (anf!=end)
	{
		if (p(*anf)) *res++ = *anf;
		++anf;
	}
	return res;
}

/** Partial specialization - not allowed for function template :-(*/
// template<typename _InputIter, typename _Function, typename Object>
// _Function
// for_each<_InputIter, _Function, Object*>
// 	(_InputIter __first, _InputIter __last, _Function __f, Object* o)
// {
// 	// concept requirements
// //	__glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
// 	for ( ; __first != __last; ++__first)
// 		(o->*__f)(*__first);
// 	return __f;
// }


 /**
	*  @brief Apply a function to every element of a sequence (const version).
	*  @param  first  An input iterator.
	*  @param  last   An input iterator.
	*  @param  f      A unary method function object.
	*  @param object  the class the method should be called for
	*  @return   @p f.
	*
	*  Applies the function object @p f to each element in the range
	*  @p [first,last).  @p f must not modify the order of the sequence.
	*  If @p f has a return value it is ignored.
	* @note this function is based on the GNU libcpp foreach function. 
	*/
// template<typename _InputIter, typename _Function, typename Object>
// _Function
// for_each(_InputIter __first, _InputIter __last, _Function __f, const Object& o)
// {
// 	// concept requirements
// //	__glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
// 	for ( ; __first != __last; ++__first)
// 		(o.*__f)(*__first);
// 	return __f;
// }

}	// namespace NExtStd


namespace std	// add some neccessary partial specilisations
{

/** Partial specialisation for using non const member functions with a binder
  *
  * See: Adapters and Binders - Overcoming problems in the design and implementation of the C++-STL<br>
  * Volker Simonis1 <br>
  * Universität Tübingen<br>
  * @author Volker Simonis1
  * Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds. 
  * Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney. 
  */
template <class A, class B, class C> 
class binder2nd<mem_fun1_ref_t<A,B,C> > : public unary_function<B,A> {
protected:
  mem_fun1_ref_t<A,B,C> op;
  C value;
public:
  binder2nd(const mem_fun1_ref_t<A,B,C>& x, const C& y) : op(x), value(y) {}
  A operator()(B& x) const {
    return op(x, value); 
  }
};

/** Partial specialisation for using non const member functions with a binder.
  *
  * Slightly modified the mem_fun1_ref_t version.
  *
  * See: Adapters and Binders - Overcoming problems in the design and implementation of the C++-STL<br>
  * Volker Simonis1 <br>
  * Universität Tübingen<br>
  * @author Benjamin Mesing
  */
template <class A, class B, class C> 
class binder2nd<mem_fun1_t<A,B,C> > : public unary_function<B,A> {
protected:
  mem_fun1_t<A,B,C> op;
  C value;
public:
  binder2nd(const mem_fun1_t<A,B,C>& x, const C& y) : op(x), value(y) {}
  A operator()(B& x) const {
    return op(x, value); 
  }
};

/** Partial specialisation allowing handing parameters by reference.
  *
  * See: Adapters and Binders - Overcoming problems in the design and implementation of the C++-STL
  * Volker Simonis1 
  * Universität Tübingen
  * @author Volker Simonis1
  * Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds. 
  * Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney. 
  */
template <class Arg1, class Arg2, class Result>
struct binary_function<Arg1, Arg2&, Result> {
    typedef Arg1 first_argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
};

}	// namespace std

#endif	// __EXTALGORITHM_2004_06_22
