![]() |
Platforms, Frameworks & Libraries »
STL »
General
Intermediate
How to use STL helper template function mem_fun in sophisticated algorithmsBy Zhaohui Xing (Joey)The article gives a sample that demonstrates the use of mem_fun in some special cases. |
VC7.1Win2K, STL, VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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.
In the demo project, a unique algorithm is designed to complete the tasks:
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){}; // Overload the operator() 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){}; // Overload the operator() 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);
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){}; // Overload the operator() 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){}; // Overload the operator() 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){}; // Overload the operator() 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; ... ... ...
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.
| You must Sign In to use this message board. | |||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 24 Jun 2005 Editor: Smitha Vijayan |
Copyright 2004 by Zhaohui Xing (Joey) Everything else Copyright © CodeProject, 1999-2009 Web19 | Advertise on the Code Project |