如何在复杂的算法中使用 STL 辅助模板函数 mem_fun






4.54/5 (7投票s)
2004年3月4日
2分钟阅读

69525

351
本文给出了一个示例,演示了在一些特殊情况下使用 mem_fun 的方法。
引言
mem_fun
是一个非常有用的 STL 辅助模板函数,它利用了与模板参数匹配的类成员函数。大多数情况下,可以直接使用 mem_fun
而无需构造类。但在一些特殊复杂的算法中,不能直接调用 mem_fun
,必须使用构造类 mem_fun_t
/cont_mem_fun_t
(用于无参数类成员函数)和 mem_fun1_t
/const_mem_fun1_t
(用于单参数类成员函数)来创建 mem_fun
对象。
在本文中,示例项目展示了如何使用 mem_fun_t
/mem_fun1_t
类创建 mem_fun
对象。
案例研究
在演示项目中,设计了一种独特的算法来完成任务
- 按特定排序顺序对列表进行排序。
- 计算列表的总和。
- 以上两个任务必须在一个过程中完成。
在设计主要算法之前,给出了两个辅助模板函数;第一个是比较两个对象
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 };
第二个是对象的求和
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 };
在此模板类中,必须给出类型转换运算符,以便从 STL for_each
函子中检索总和。
主要算法设计如下
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 };
在 stlalgor.cpp 中,示例类演示了此算法的应用。
类 CDblCounter
的成员函数 "Get
" 和类 CStrCounter
的 "GetStr
" 可以用作模板 TComparsion
和 TSummation
的函子。要将这两个类成员函数作为模板参数传递,必须使用 STL mem_fun
作为 TComparsion
和 TSummation
的成员函数。但是,在此算法实现中,不能直接在这些模板中调用 mem_fun
,因此必须使用构造类 mem_fun_t
来创建传递给算法的 mem_fun
对象。
以下代码
typedef mem_fun_t<double, CDblCounter> CDblMemFuncT; ...... typedef mem_fun_t<string, CStrCounter> CStrMemFuncT;
定义了用于将 CDblCounter::Get
和 CStrCounter::GetStr
传递给 mem_fun
的具体构造类。这两个定义对于算法调用 mem_fun
非常重要。
以下定义给出了具体的比较和求和类,其中实现了用于适配 CDblCounter::Get
和 CStrCounter::GetStr
的 mem_fun
对象,作为类成员函数。
typedef TComparsion<CDblCounter, CDblMemFuncT> CDblCmpFunctor; typedef TSummation<CDblCounter, CDblMemFuncT, double> CDblSumFunctor; ...... typedef TComparsion<CStrCounter, CStrMemFuncT> CStrCmpFunctor; typedef TSummation<CStrCounter, CStrMemFuncT, string> CStrSumFunctor;
最后,具体算法类定义如下
typedef TSortSumAlgor<CDblArray, CDblCmpFunctor, CDblSumFunctor, double> CDblAglor; ...... typedef TSortSumAlgor<CStrArray, CStrCmpFunctor, CStrSumFunctor, string> CStrAglor;
该图显示了在复杂算法中应用 mem_fun
的步骤
该算法可以应用于 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);
在 templdefs.h 和 stlalgor.cpp 中,也演示了 mem_fun1_t
的用法。
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);
更新的示例代码(2005 年 6 月)
在更新的示例代码中,新的模板和类演示了如何在算法设计和实现中应用 bind1st
/bind2nd
辅助模板函数。设计 bind1st
/bind2nd
的函子模板的关键点是必须显式定义 first_argument_type
、second_argument_type
、result_type
。
关于 bind1st
/bind2nd
的示例代码是
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; ... ... ...
结论
mem_fun
是一个非常强大的函子,用于在算法过程中操作和处理类对象的行为和功能。正确构建 mem_fun
对象非常重要,有时必须使用 mem_fun_t
/mem_fun1_t
构造类来创建 mem_fun
对象。