//  (C) Porkolab 2003
//
//  A.6.20.
//  Member function adapter



// This is syntax error!
void draw_all(list<Shape*>& c)
{
    for_each(c.begin(),c.end(),&Shape::draw);   // oops! error
}


/*
 *  In the STL:
 *
 */

template<class R, class T> class mem_fun_t : public unary_function<T*,R> {
    R (T::*pmf)();
public:
    explicit mem_fun_t(R (T::*p)()) :pmf(p) {}
    R operator()(T* p) const { return (p->*pmf)(); }    // call through pointer
};

template<class R, class T> mem_fun_t<R,T> mem_fun(R (T::*f)())
{
    return mem_fun_t<R,T>(f);
}


/*
 *  Usage of a member function adapter
 *
 */

void draw_all(list<Shape*>& lsp) // call 0-argument member through pointer to object
{
    for_each(lsp.begin(),lsp.end(),mem_fun(&Shape::draw));  // draw all shapes
}


/*
 *  And the same with arguments
 *
 */

template<class R, class T> mem_fun_t<R,T> mem_fun(R (T::*f)());
// and versions for unary member, for const member, and const unary member (see table in _algo.adapter_)

template<class R, class T> mem_fun_ref_t<R,T> mem_fun_ref(R (T::*f)());
// and versions for unary member, for const member, and const unary member (see table in _algo.adapter_)


/*
 *  Usage
 *
 */

void f(list<string>& ls)
// use member function that takes no argument for object
{
    typedef list<string>::iterator LSI;
    LSI p = find_if(ls.begin(),ls.end(),mem_fun_ref(&string::empty));   // find ""
}

void rotate_all(list<Shape*>& ls, int angle)
// use member function that takes one argument through pointer to object
{
    for_each(ls.begin(),ls.end(),bind2nd(mem_fun(&Shape::rotate),angle));
}