65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.54/5 (7投票s)

2004年3月4日

2分钟阅读

viewsIcon

69525

downloadIcon

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 对象。

案例研究

在演示项目中,设计了一种独特的算法来完成任务

  1. 按特定排序顺序对列表进行排序。
  2. 计算列表的总和。
  3. 以上两个任务必须在一个过程中完成。

在设计主要算法之前,给出了两个辅助模板函数;第一个是比较两个对象

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" 可以用作模板 TComparsionTSummation 的函子。要将这两个类成员函数作为模板参数传递,必须使用 STL mem_fun 作为 TComparsionTSummation 的成员函数。但是,在此算法实现中,不能直接在这些模板中调用 mem_fun,因此必须使用构造类 mem_fun_t 来创建传递给算法的 mem_fun 对象。

以下代码

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

定义了用于将 CDblCounter::GetCStrCounter::GetStr 传递给 mem_fun 的具体构造类。这两个定义对于算法调用 mem_fun 非常重要。

以下定义给出了具体的比较和求和类,其中实现了用于适配 CDblCounter::GetCStrCounter::GetStrmem_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.hstlalgor.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_typesecond_argument_typeresult_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 对象。

如何在复杂算法中使用 STL 辅助模板函数 mem_fun - CodeProject - 代码之家
© . All rights reserved.