## Introduction

`mem_fun`

is a very useful STL helper template function which takes advantage of the class member function matching the template parameters. Most of the time, `mem_fun`

can be directly used without the construction class. But in some special sophisticated algorithmd, the `mem_fun`

can not be called directly, and the construction classes `mem_fun_t`

/`cont_mem_fun_t`

(for non parameter class member functions) and `mem_fun1_t`

/`const_mem_fun1_t`

(for one parameter class member functions) must be used to create the `mem_fun`

object.

In this article, the sample project shows how to create `mem_fun`

object with `mem_fun_t`

/`mem_fun1_t`

class.

## Case Study

In the demo project, a unique algorithm is designed to complete the tasks:

- Sort the list with specific sort order.
- Calculate the summation of list.
- Above two tasks must be completed in a single procedure.

Before designing the main algorithm, two helper template functions are given out; the first is the comparison of two objects:

template<typename TType, typename TFunc> class TComparsion
{
public:
TComparsion(const TFunc& func,
bool bAsc = true):m_fFunc(func), m_bAsc(bAsc){};
bool operator () (TType* t1, TType* t2)
{
if(m_bAsc)
return (m_fFunc(t1) < m_fFunc(t2));
else
return (m_fFunc(t2) < m_fFunc(t1));
}
private:
TFunc m_fFunc;
bool m_bAsc;
};

The second is the summation of the objects:

template<typename TType, typename TFunc, typename TFuncOut>
class TSummation
{
public:
TSummation(const TFunc& func,const TFuncOut tVal = 0)
:m_fFunc(func), m_tSummation(tVal){};
void operator()(TType* t)
{
if(t)
{
m_tSummation += m_fFunc(t);
}
}
operator TFuncOut(){return m_tSummation;}
private:
TFunc m_fFunc;
TFuncOut m_tSummation;
};

In this template class, the type conversion operator must be given out for retrieving the summation from STL `for_each`

functor.

The main algorithm is designed as:

template <typename TList, typename TCmp, typename TSum,
typename TSumVal>class TSortSumAlgor
{
public:
TSortSumAlgor(const TCmp& fcmp, const TSum& fsum)
:m_Fcmp(fcmp), m_Fsum(fsum){};
TSumVal operator()(TList& t)
{
std::stable_sort<TList::iterator>(t.begin(), t.end(), m_Fcmp);
return std::for_each<TList::iterator>(t.begin(), t.end(), m_Fsum);
}
private:
TCmp m_Fcmp;
TSum m_Fsum;
};

In *stlalgor.cpp*, the sample classes demonstrate the application of this algorithm.

The member function "`Get`

" of class `CDblCounter`

and "`GetStr`

" of class `CStrCounter`

can be used as the functor for the templates `TComparsion`

and `TSummation`

. To pass these two class member functions as the template parameters, the STL `mem_fun`

must be used as the member function of `TComparsion`

and `TSummation`

. But, in this algorithm implementation, the `mem_fun`

can not be called directly in these templates, so the construction class `mem_fun_t`

must be used to create the `mem_fun`

object being passed to the algorithm.

The following code:

typedef mem_fun_t<double, CDblCounter> CDblMemFuncT;
......
typedef mem_fun_t<string, CStrCounter> CStrMemFuncT;

defines the concrete construction class for passing `CDblCounter::Get`

and `CStrCounter::GetStr`

to `mem_fun`

. These two definitions are very important for the algorithm calling `mem_fun`

.

The following definitions give out the concrete comparison and summation class in which the `mem_fun`

objects, which adapt `CDblCounter::Get`

and `CStrCounter::GetStr`

, are implemented as the class member functions.

typedef TComparsion<CDblCounter, CDblMemFuncT> CDblCmpFunctor;
typedef TSummation<CDblCounter, CDblMemFuncT, double> CDblSumFunctor;
......
typedef TComparsion<CStrCounter, CStrMemFuncT> CStrCmpFunctor;
typedef TSummation<CStrCounter, CStrMemFuncT, string> CStrSumFunctor;

Finally the concrete algorithm classes are defined as:

typedef TSortSumAlgor<CDblArray, CDblCmpFunctor,
CDblSumFunctor, double> CDblAglor;
......
typedef TSortSumAlgor<CStrArray, CStrCmpFunctor,
CStrSumFunctor, string> CStrAglor;

The figure shows the steps of applying `mem_fun`

in a complicated algorithm:

The algorithm can be applied as the code shown in *stlalgor.cpp*:

CDblArray dList1;
...
...
...
CDblCmpFunctor fCmp(std::mem_fun<double, CDblCounter>
(&CDblCounter::Get), true);
CDblSumFunctor fSum(std::mem_fun<double, CDblCounter>
(&CDblCounter::Get), 0.0);
CDblAglor pAglor(fCmp, fSum);
double dSum = pAglor(dList1);
...
...
...
CStrArray sList;
...
...
...
CStrCmpFunctor sfCmp(std::mem_fun<string, CStrCounter>
(&CStrCounter::GetStr), true);
CStrSumFunctor sfSum(std::mem_fun<string, CStrCounter>
(&CStrCounter::GetStr), "Programming Language:");
CStrAglor sAglor(sfCmp, sfSum);
string sSum = sAglor(sList);

In *templdefs.h* and *stlalgor.cpp*, the use of `mem_fun1_t`

is also demonstrated.

template<typename TType, typename TFunc,
typename TFuncOut, typename TParam>class TSummation1
{
public:
TSummation1(const TFunc& func, const TParam tParam,
const TFuncOut tVal = 0):m_fFunc(func), m_tParam(tParam),
m_tSummation(tVal){};
void operator()(TType* t)
{
if(t)
{
m_tSummation += m_fFunc(t, m_tParam);
}
}
operator TFuncOut(){return m_tSummation;}
private:
TFunc m_fFunc;
TParam m_tParam;
TFuncOut m_tSummation;
};
...
...
...
typedef mem_fun1_t<double, CDblCounter, double> CDblMemFunc1T;
typedef TSummation1<CDblCounter, CDblMemFunc1T,
double, double> CDblSum1Functor;
...
...
...
CDblSum1Functor fSum1(std::mem_fun<double, CDblCounter,
double>(&CDblCounter::Calc), 8.0, 0.0);
dSum = for_each(dList1.begin(), dList1.end(), fSum1);

## Updated Sample Code (June 2005)

In the updated sample code, the new template and class demonstrate how to apply `bind1st`

/`bind2nd`

helper template function in the algorithm design and implementation. The key points in designing the functor template for `bind1st`

/`bind2nd`

are that the `first_argument_type`

, `second_argument_type`

, `result_type`

must be explicitly defined.

The sample code with regards to `bind1st`

/`bind2nd`

is:

template<typename TList, typename TType,
typename TValue, typename TFunc>class TSearch
{
public:
TSearch(const TFunc& func): m_fFunc(func){};
TType operator()(TList& tl, const TValue& tv)
{
TType pRet = 0;
TList::iterator iter;
iter = std::find_if<TList::iterator>(tl.begin(),
tl.end(), std::bind2nd(m_fFunc, tv));
if(iter != tl.end())
{
pRet = (*iter);
}
return pRet;
}
private:
TFunc m_fFunc;
};
template<typename TType1, typename TType2,
typename TReturn, typename TFunc>class TBinder
{
public:
typedef TType1 first_argument_type;
typedef TType2 second_argument_type;
typedef TReturn result_type;
TBinder(const TFunc& func):m_fFunc(func){};
result_type operator()(first_argument_type tc,
second_argument_type tv) const
{
result_type vRet;
vRet = m_fFunc(tc, tv);
return vRet;
}
private:
TFunc m_fFunc;
};
template<typename TClass, typename TValue,
typename TFunc>class TEqualFunctor
{
public:
TEqualFunctor(const TFunc& func):m_fFunc(func){};
bool operator()(TClass tc, const TValue& tv) const
{
bool bRet = false;
bRet = (tv == m_fFunc(tc));
return bRet;
}
private:
TFunc m_fFunc;
};
...
...
...
typedef vector<CPersonInfo*> CPersonArray;
typedef TSeqDeletor<CPersonInfo> CPersonDel;
typedef TDealloc<CPersonArray, CPersonDel> CPersonClean;
typedef const_mem_fun_t<int, CPersonInfo> CPersonMemT;
typedef TEqualFunctor<CPersonInfo*, int, CPersonMemT> CPersonFinder;
typedef TBinder<CPersonInfo*, int, bool, CPersonFinder> CPersonChecker;
typedef TSearch<CPersonArray, CPersonInfo*,
int, CPersonChecker> CPersonSearch;
...
...
...

## Conclusion

The `mem_fun`

is a very powerful functor to manipulate and process the class object's behavior and functionality in the algorithm procedure. Properly building the `mem_fun`

object is very important and sometimes the `mem_fun_t`

/`mem_fun1_t`

construction class must be used to create the `mem_fun`

object.