函数配接器

概念

所谓的“函数配接器”是指能够将仿函数另一个仿函数(或者某个值,或者另一个仿函数)结合起来的仿函数。函数配接器也声明与<functional>中。

通过函数配接器,我们可以把多个仿函数结合起来,形成强大的表达式,这种编程方式叫做functional composition(功能复合、函数复合)。

STL中预定义了四种类型的函数配接器,如图表1,函数配接器使用效果见例子1.
例子1
/****************************************************************
*函数名称:FuncAdapter
*功    能:预定义的函数配接器举例
*作    者:Jin
*日    期:2016年6月7日
****************************************************************/
void FuncAdapter()
{
    typedef vector<int> IntVector;
    IntVector Container;

    Container.push_back(10);
    Container.push_back(15);
    Container.push_back(20);
    Container.push_back(9);

    cout << "element in the container is: ";
    copy(Container.begin(), Container.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    //bind2nd范式: param > 15
    //output:1个
    int nNumber1 = count_if(Container.begin(), 
                           Container.end(),
                           bind2nd(greater<int>(), 15));
    cout << "The number of elements in Container greater than 15 is: "
         << nNumber1 << endl;
    
    //bind1st范式: 15 > param
    int nNumber2 = count_if(Container.begin(), 
                            Container.end(),
                            bind1st(greater<int>(), 15));
    cout << "The number of elements in Container less than  15 is: "
         << nNumber2 << endl;

    // not1 bind1st范式:  !(param > 15) == (param <= 15)
    int nNumber3 = count_if(Container.begin(), 
                            Container.end(),
                            not1(bind2nd(greater<int>(), 15)));
    cout << "The number of elements in Container less than or equal to 15 is: "
         << nNumber3 << endl;

    sort(Container.begin(),Container.end(),less<int>());
    PrintElements(Container, "descending: ");
    //not2 范式 !op(param1, param2)
    sort(Container.begin(),Container.end(),not2(less<int>()));
    PrintElements(Container, "Ascending: ");
}

运行结果:



成员函数配接器

为了能够将类别中的成员函数和仿函数结合起来,需要是使用成员函数配接器,将成员函数转变仿函数,STL中预定义了两种成员函数配接器接口见表2.
成员函数配接代码见例子2.

例子2

class Person
{
public:
    //member function
    void Print() const
    {
        cout << m_strName << endl;   
    }
    //member function
    void PrintWithPrefix(string strPrefix) const
    {
        std::cout << strPrefix << m_strName << endl;
    }
    //construction function
    Person(string strName):m_strName(strName){}

private:
    string m_strName;
};

/****************************************************************
*函数名称:MemberFunction
*功    能:针对成员函数设计的函数配接器
*作    者:Jin
*日    期:2016年6月8日
****************************************************************/
void MemberFuncAdapter()
{
   vector<Person> PersonVector;     //vector中是对象
   vector<Person*> PtrPersonVector; //指针序列

   const int nMaxPerson = 5;
   string strNames[nMaxPerson] = 
   {
        "David",
        "Kangkang",
        "Hua",
        "Mike",
        "Lily"
   };

   for (int i = 0; i < nMaxPerson; i++)
   {
       Person per(strNames[i]);;
       PersonVector.push_back(per);

       Person *PtrPer = new Person(strNames[i]);
       PtrPersonVector.push_back(PtrPer);
   }

   //it is object in the vector: call print member function 
   for_each(PersonVector.begin(), PersonVector.end(), mem_fun_ref(&Person::Print));
   //it is object in the vector: call PrintWithPrefix member function 
   for_each(PersonVector.begin(), 
            PersonVector.end(), 
            bind2nd(mem_fun_ref(&Person::PrintWithPrefix), "person:"));
   
   cout << endl << "ptr object: " << endl;
   //it is ptr in the vector: call print member function 
   for_each(PtrPersonVector.begin(), PtrPersonVector.end(), mem_fun(&Person::Print));
   //it is ptr in the vector: call PrintWithPrefix member function 
   for_each(PtrPersonVector.begin(), 
            PtrPersonVector.end(), 
            bind2nd(mem_fun(&Person::PrintWithPrefix), "PersonName:"));
    
   //删除申请的空间
   for (unsigned i = 0; i < PtrPersonVector.size(); i++)
   {
       delete PtrPersonVector[i];
   }

}
运行效果:


一般函数配接器

针对非成员函数而设计的函数配接器是ptr_fun见表3,从而可以和仿函数结合起来。具体代码使用见例子3。
例子3
/****************************************************************
*函数名称:CommonFuncAdapter
*功    能:用于一般函数身上的函数配接器
*作    者:Jin
*日    期:2016年6月14日
****************************************************************/
void CommonFuncAdapter()
{
    vector <char*> v1;
    vector <char*>::iterator Iter1, RIter;

    v1.push_back ("Open");
    v1.push_back ("up");
    v1.push_back ("the");
    v1.push_back ("pearly");
    v1.push_back ("gates");

    cout << "Original sequence contains: " ;
    for (Iter1 = v1.begin(); Iter1 != v1.end(); Iter1++)
    {
        cout << *Iter1 << " ";
    }  
    cout << endl;

    // To search the sequence for "pearly"
    // use a pointer_to_function conversion
    RIter = find_if(v1.begin(),
                    v1.end(),
                    not1(bind2nd(ptr_fun(strcmp), "pearly")));

    if (RIter != v1.end())  
    {
        cout << "The search for 'pearly' was successful.\n";
        cout << "The next character string is: " 
             << *++RIter 
             << "." 
             << endl;
    }
}
运行结果:


自定义仿函数的可配接性

在某些情况下,我们需要编写自己的仿函数,但是希望它们能够和函数配接器搭配运用,就必须满足某些条件:

提供一些成员函数来反映其参数和返回值的型别,STL提供了如下的数据结构:

// TEMPLATE STRUCT unary_function
template<class _Arg, class _Result>
struct unary_function
{	
	// base class for unary functions
	typedef _Arg argument_type;
	typedef _Result result_type;
};

// TEMPLATE STRUCT binary_function
template<class _Arg1, class _Arg2, class _Result>
struct binary_function
{	
	// base class for binary functions
	typedef _Arg1 first_argument_type;
	typedef _Arg2 second_argument_type;
	typedef _Result result_type;
};
仿函数上述两种形式之一,就能轻松满是“可配接”的条件,例如预定义仿函数great,less都继承了上述结构,具体“可配接”性的分析后文再单独分享。

template<class _Ty>
struct less: public binary_function<_Ty, _Ty, bool>
{	
	// functor for operator<
	bool operator()(const _Ty& _Left, const _Ty& _Right) const
	{	
		// apply operator< to operands
		return (_Left < _Right);
	}
};

template<class _Ty>
struct negate : public unary_function<_Ty, _Ty>
{	
	// functor for unary operator-
	Ty operator()(const _Ty& _Left) const
	{	
		// apply operator- to operand
		return (-_Left);
	}
};

posted @ 2016-06-19 23:10  小怪兽&奥特曼  阅读(173)  评论(0编辑  收藏  举报