#ifndef FNOBJTFN_H
#define FNOBJTFN_H

#include <fnobj.h>

/*!
\brief Convert a member function with return type A0 and no arguments to a functional object.
\par Example
\verbatim
  fnobj0<void> *ptr;
  hat3 h3;
  //h3.sumfunc(); 
  fnobj0Tfn<hat3,void> ph3(h3,&hat3::sumfunc);
  ptr = &ph3;
  (*ptr)();
\endverbatim
*/
template<class T, class A0 >
class fnobj0Tfn : public fnobj0<A0>
{
public:

   T* data;
   typedef A0 (T::*Fptr)();
   Fptr fn;

   fnobj0Tfn( T & data_, Fptr fn_)
     : data(&data_), fn(fn_) {}

   A0 operator () ()
     { return (data->*fn)(); }

};

template<class T, class A0 >
class fnobj0constTfn : public fnobj0const<A0>
{
public:

   T* data;
   typedef A0 (T::*Fptr)() const;
   Fptr fn;

   fnobj0constTfn( T & data_, Fptr fn_)
     : data(&data_), fn(fn_) {}

   A0 operator () () const
     { return (data->*fn)(); }

};



/*!
\brief Convert a member function with return type A0 and one argument to a functional object.
\par Example
\verbatim

\endverbatim
*/
template<class T, class A0, class A1>
class fnobj1Tfn : public fnobj1<A0,A1>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1);
  Fptr fn;

  fnobj1Tfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1)
    { return (data->*fn)(arg1); }
};

template<class T, class A0, class A1>
class fnobj1constTfn : public fnobj1const<A0,A1>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1) const;
  Fptr fn;

  fnobj1constTfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1) const
    { return (data->*fn)(arg1); }
};

/*!
\brief Convert a member function with return type A0 and two arguments to a functional object.
\par Example
\verbatim

\endverbatim
*/
template<class T, class A0, class A1, class A2>
class fnobj2Tfn : public fnobj2<A0,A1,A2>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1,A2);
  Fptr fn;

  fnobj2Tfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1,A2 arg2)
    { return (data->*fn)(arg1,arg2); }
};

template<class T, class A0, class A1, class A2>
class fnobj2constTfn : public fnobj2const<A0,A1,A2>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1,A2) const;
  Fptr fn;

  fnobj2constTfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1,A2 arg2) const
    { return (data->*fn)(arg1,arg2); }
};

/*!
\brief Convert a member function with return type A0 and three arguments to a functional object.
\par Example
\verbatim

\endverbatim
*/
template<class T, class A0, class A1, class A2, class A3>
class fnobj3Tfn : public fnobj3<A0,A1,A2,A3>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1,A2,A3);
  Fptr fn;

  fnobj3Tfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1, A2 arg2, A3 arg3)
    { return (data->*fn)(arg1,arg2,arg3); }
};

template<class T, class A0, class A1, class A2, class A3>
class fnobj3constTfn : public fnobj3const<A0,A1,A2,A3>
{
public:

  T* data;
  typedef A0 (T::*Fptr)(A1,A2,A3) const;
  Fptr fn;

  fnobj3constTfn( T & data_, Fptr fn_)
    : data(&data_), fn(fn_) {}

  A0 operator () (A1 arg1, A2 arg2, A3 arg3) const
    { return (data->*fn)(arg1,arg2,arg3); }
};




#endif



