
#ifndef CS235_FUNCTIONAL_H
#define CS235_FUNCTIONAL_H

/**
CLASS
    BinaryFunction

DESCRIPTION
    BinaryFunction is an abstract class that as the base 
    class for function objects that take two parameters of 
    type T1 and T2 and returns an object of type R.  
    The parameter types T1, T2, and R may, or may not, all 
    be the same type.

    The BinaryFunction class defines one pure virtual function,
    which is operator().  Any class which inherits fron BinaryFunction
    must override the operator() before it can be used.

    BinaryFunction also defines three typedefs for BinaryFunction 
    objects. They are:
    <li>first_arg_type,
    <li>second_arg_type, and
    <li>result_type;
*/
template <class T1, class T2, class R> struct BinaryFunction
{
    public:
	typedef T1 first_arg_type;
	typedef T2 second_arg_type;
	typedef R result_type;

    /**
    A pure virtual operator.  Child class <b>must</b> implement
    operator() before they can be instantiated.  A binary
    function takes two paramters of type T1 and T2 and returns
    an object of type R
    */
    virtual R operator() (T1, T2) const = 0;

};

/**
CLASS
    Predicate

KEYWORDS
    BinaryFunction

DESCRIPTION
    Predicate pure abstract specialization of BinaryFunction.  A
    predicate takes two parameters of type T and returns a bool
*/
template <class T> struct Predicate : public BinaryFunction<T, T, bool>
{
};

/**
CLASS
    Less

KEYWORDS
    BinaryFunction, Predicate

DESCRIPTION
    A predicate function object that compares two objects of
    type T with operator <
*/
template <class T> struct Less : public Predicate<T>
{
    public:
	virtual bool operator()(T x, T y) const
	{
		return x < y;
	}
};

/**
CLASS
    Greater

KEYWORDS
    BinaryFunction, Predicate

DESCRIPTION
    A predicate function object that compares two objects of
    type T with operator >
*/
template <class T> struct Greater : public Predicate<T>
{
    public:
    /**
    Implementation of operator() that takes two objects of type T and
    returns a bool.
    */
	virtual bool operator()(T x, T y) const
	{
		return x > y;
	}
};

#endif
