12,549,720 members (47,719 online)
alternative version

61.5K views
16 bookmarked
Posted

# How to use STL helper template function mem_fun in sophisticated algorithms

, 24 Jun 2005
 Rate this:
The article gives a sample that demonstrates the use of mem_fun in some special cases.

## 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:

1. Sort the list with specific sort order.
2. Calculate the summation of list.
3. 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) // Ascending sort
return (m_fFunc(t1) < m_fFunc(t2));
else       // Descending sort
return (m_fFunc(t2) < m_fFunc(t1));
}
private:
TFunc m_fFunc; // The member function object
bool  m_bAsc;  // Sort order, true: ascending sort, false: descending sort
};```

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);
}
}

// Type cast
operator TFuncOut(){return m_tSummation;}
private:
TFunc     m_fFunc;           // The member function object
TFuncOut  m_tSummation;    // The return value
};```

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)
{        // Sort the list
std::stable_sort<TList::iterator>(t.begin(), t.end(), m_Fcmp);
// Get the summation
return std::for_each<TList::iterator>(t.begin(), t.end(), m_Fsum);
}
private:
TCmp     m_Fcmp;   // Comparsion functor
TSum     m_Fsum;   // Summation functor
};```

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;    // The member function object
TParam      m_tParam;       // The member function parameter
TFuncOut    m_tSummation;   // The return value
};
...
...
...
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;   // The member function object
};

template<typename TType1, typename TType2,
typename TReturn, typename TFunc>class TBinder
{
public:
// The three key type definitions
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;   // The member function object
};

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;   // The member function object
};

...
...
...
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.

A list of licenses authors might use can be found here

## Share

No Biography provided

## You may also be interested in...

 Pro Pro

 First Prev Next
 Very useful to know. WREY6-Mar-04 5:52 WREY 6-Mar-04 5:52
 Re: Very useful to know. Zhaohui Xing (Joey)6-Mar-04 6:33 Zhaohui Xing (Joey) 6-Mar-04 6:33
 Last Visit: 31-Dec-99 18:00     Last Update: 22-Oct-16 21:06 Refresh 1