一:STL预定义函数配接器的使用
STL预定义的函数配接器
1. bind1st(op, value)
2. bind2st(op, value)
3. not1(param)
4. not2(param1,param2)
函数配接器可以将仿函数和另一个仿函数结合起来。
函数配接器本身也是仿函数。
二元函数配接器示例:
find_if( coll.begin(), coll.end(), bind2nd(greater<int>(),42) );
以上例句中,bind2nd将仿函数greater<int>()和第二个参数整型数42结合起来,查找条件就变成了“大于42”。
其中greater<int>为STL预定义的仿函数,接收两个参数比较,第一个参数为coll中元素,第二个参数42作为greater<int>的内部参数保存,上面的语句相当于以下伪代码的逻辑(注意只是相等逻辑,非STL实现):
greater<int> functorGreater; //在find_if语句内部,仿函数会创建一个实例对象 for(std::vector<int>::const_iterator It = coll.begin(); It != coll.end(); ++It ) { if( functorGreater(*It,42) ) //调用仿函数greater<int>内部的重载操作符"()"完成比较操作 return It; return coll.end(); }
类似的,一元函数配接器:
find_if( coll.begin(), coll.end(), bind1nd(greater<int>(),42) );
只是想当把以上伪代码中的
if( functorGreater(*It,42) )
改成
if( functorGreater(42,*It) )
可见,仿函数命名bind1st,bind2nd意思是指定第几个元素是要作为“被绑定的仿函数”的内部参数的。
not1()将结果取反:
find_if( coll.begin(), coll.end(), not1(bind2nd(greater<int>(),42)) );
返回小于等于42的值。
not1()与not2()区别只是后者用于接收两个形参的表达式: not2(op) //这里的op接收两个形参,not2将op的返回值取反
二:针对成员函数的函数配接器
成员函数的函数配接器(注意op均为const),同普通函数配接器,只是被配接的函数是类的成员函数。
1.mem_fun_ref(op)
2.mem_fun(op)
示例(Win7 64 + Visual studio 2010):
#include <iostream> #include <vector> #include <functional> #include <algorithm> #include <iterator> using namespace::std; class TestClass { public: TestClass(int i):index(i){} void print() const { cout<<"TestClass"<<index<<endl;; } int operator()() { return index++; } private: int index; }; int main() { vector<TestClass> testVector; generate_n(back_inserter(testVector),10,TestClass(1)); for_each(testVector.begin(),testVector.end(), mem_fun_ref(&TestClass::print)); //遍历输出 return 0; }
以上代码中,mem_fun_ref调用了TestClass中的print成员函数,而且print函数必须为const。
mem_fun和mem_fun_ref区别在于,后者调用的是类引用类型,前者是指针类型:
若testVector类型为vector<TestClass*>
则需要调用mem_fun(&TestClass::print)
三:一般函数的函数配接器
参考成员函数的配接器,基本没啥不同。
如有全局函数
void printTestClass(TestClass& refTC) { refTC.print(); }
调用:
for_each(testVector.begin(),testVector.end(), ptr_fun( printTestClass ) );
四:自定义仿函数的函数配接器
自定义仿函数需要提供类型成员来指定参数和返回值类型,可继承以下STL中定义的模板来确定规范化:
template<class Arg,class Result> struct unary_function { typedef Arg argument_type; typedef Result result_type; } template<class Arg1,class Arg2,class Result> struct binary_function { typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result result_type; }