bind1st, bind2nd, mem_fun, mem_fun_ref, ptr_fun这几个的使用
bind1st, bind2nd, mem_fun, mem_fun_ref,这三个函数的使用
bind1st 为一个有两个参数的函数绑定第一个参数, 名字已经很明确了 bind first parameter
bind2nd 为一个有两个参数的函数绑定第二个参数.
如果是自定义的函数对象需要去继承unary_function,binary_function
首先看一下下面几个辅助函数和结构体,它们是bind1st和bind2nd的基础
1.unary_function
这个结构体负责对一元函数的描述:
1 template <class _Arg, class _Result>
2 struct unary_function
3 {
4 typedef _Arg argument_type; ///< @c argument_type is the type of the
5 /// argument (no surprises here)
6
7 typedef _Result result_type; ///< @c result_type is the return type
8 };
2.binary_function
这个结构体负责对二元函数的描述:
1 template <class _Arg1, class _Arg2, class _Result>
2 struct binary_function
3 {
4 typedef _Arg1 first_argument_type; ///< the type of the first argument
5 /// (no surprises here)
6
7 typedef _Arg2 second_argument_type; ///< the type of the second argument
8 typedef _Result result_type; ///< type of the return type
9 };
3.binder1st类
1 template <class _Operation>
2 class binder1st
3 : public unary_function < typename _Operation::second_argument_type,
4 typename _Operation::result_type >
5 {
6 protected:
7 _Operation op;
8 typename _Operation::first_argument_type value;
9 public:
10 binder1st( const _Operation& __x,
11 const typename _Operation::first_argument_type& __y )
12 : op( __x ), value( __y ) {}
13
14 typename _Operation::result_type
15 operator()( const typename _Operation::second_argument_type& __x ) const
16 { return op( value, __x ); }
17
18 // _GLIBCXX_RESOLVE_LIB_DEFECTS
19 // 109. Missing binders for non-const sequence elements
20 typename _Operation::result_type
21 operator()( typename _Operation::second_argument_type& __x ) const
22 { return op( value, __x ); }
23 };
注意7~8行的op和value,分别用来保存绑定的函数操作和值。而在14~16行,可以看到这里直接使用op来处理value和__x参数。
从这两段代码可以看到,binder1st可以把二元函数间接变成一元函数(通过binder1st的operator()调用)。另外,14~15行的result_type、
second_argument_type和first_argument_type也意味着,如果我们自己要写一个可以由bind1st绑定的函数,那么最好是先从unary_function
和binary_function结构体中继承相应的traits,然后再实现operator()函数。
4.bind1st
bind1st函数实质上就是返回了一个binder1st类对象,注意看下面第7行代码:
1 /// One of the @link s20_3_6_binder binder functors@endlink.
2 template <class _Operation, class _Tp>
3 inline binder1st<_Operation>
4 bind1st( const _Operation& __fn, const _Tp& __x )
5 {
6 typedef typename _Operation::first_argument_type _Arg1_type;
7 return binder1st<_Operation>( __fn, _Arg1_type( __x ) );
8 }
5.binder2nd和bind2nd
与binder1st和bind1st类似,只是使用Op调用的参数位置发生了变化而已
什么时候使用呢?
当我们的回调函数有两个参数,可是程序代码在调用这个回调的时候,只有一个参数,怎么办呢,这时候就可以用 bind1st 或者 bind2nd. 那么到的是用 bind1st 还是 bind2nd 呢, 这个时候就要看 回调的参数和你需要的参数的顺序了,如果例程代码调用你的回调函数传入的参数,其实是你想要的第二个参数,那么就用 bind1st(para1, para2) 在para2 中传入你的第一个参数;同理,如果例程代码调用你的回调函数传入的参数,其实是你想要的第一个参数,那么就用 bind2nd(para1, para2) 在para2 中传入你的第二个参数,是不是很简单
在说 mem_fun, mem_fun_ref
这是调用 成员函数, 有 _ref 的很明显是 调用 类引用
的成员函数, mem_fun 并不是调用类的成员函数,是类指针
的成员函数
// mem_fun example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
class CPerson
{
public:
CPerson(string name):m_name(name)
{
}
virtual ~CPerson()
{
}
void printname()
{
cout << m_name << endl;
}
void printcompany( string strcompany)
{
cout << m_name << " " << strcompany << endl;
}
private:
string m_name;
};
int _tmain(int argc, _TCHAR* argv[])
{
CPerson p1("tom");
CPerson p2("jerry");
vector <CPerson> vecperson;
vecperson.push_back(p1);
vecperson.push_back(p2);
for_each(vecperson.begin(), vecperson.end(), mem_fun_ref(&CPerson::printname));
//
// mem_fun
//
CPerson * pp1 = &p1;
CPerson * pp2 = &p2;
vector <CPerson*> vecpersonptr;
vecpersonptr.push_back(pp1);
vecpersonptr.push_back(pp2);
for_each(vecpersonptr.begin(), vecpersonptr.end(), mem_fun(&CPerson::printname));
return 0;
}
如果我的成员函数有参数那又该怎么办呢?
很自然我们想到 bind1st(mem_fun, ...) bind1st(mem_fun_ref, ...);且慢,到底是bind1st 还是 bind2nd 呢,这个就要看具体代码了,如本例的 printcompany,他的参数 strcompany 就是第二个参数,为嘛是第二个参数不解释了,所以应该是 bind2nd(..., ...)
for_each(vecpersonptr.begin(), vecpersonptr.end(), bind2nd(mem_fun(&CPerson::printcompany), "abc") );
什么?你想看看 bind1st 的例子,这个也好办需要多加几行代码
vector <string> vecstring;
vecstring.push_back("abc");
vecstring.push_back("def");
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun(&CPerson::printcompany), pp1) );
最终的代码就是这个样子
int _tmain(int argc, _TCHAR* argv[])
{
CPerson p1("tom");
CPerson p2("jerry");
vector <CPerson> vecperson;
vecperson.push_back(p1);
vecperson.push_back(p2);
for_each(vecperson.begin(), vecperson.end(), mem_fun_ref(&CPerson::printname));
//
// mem_fun
//
CPerson * pp1 = &p1;
CPerson * pp2 = &p2;
vector <CPerson*> vecpersonptr;
vecpersonptr.push_back(pp1);
vecpersonptr.push_back(pp2);
for_each(vecpersonptr.begin(), vecpersonptr.end(), mem_fun(&CPerson::printname));
for_each(vecpersonptr.begin(), vecpersonptr.end(), bind2nd(mem_fun(&CPerson::printcompany), "abc") );
vector <string> vecstring;
vecstring.push_back("abc");
vecstring.push_back("def");
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun(&CPerson::printcompany), pp1) );
return 0;
}
还想看 mem_fun_ref 的例子,好贪心呀
for_each(vecperson.begin(), vecperson.end(), bind2nd(mem_fun_ref(&CPerson::printcompany), "abc") );
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun_ref(&CPerson::printcompany), p1) );
好大功告成,编译,嗯,出错了
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun_ref(&CPerson::printcompany), p1) ); compile error
为嘛嗫?
仔细看源码,呵呵原来是 const 的问题 bind1st 的两个参数都是 const 类型, 可是 mem_fun_ref 的参数偏偏不要const的
看来 bind1st 和 mem_fun_ref 不兼容呀
怎么办呢???????
也好办 直接把 CPerson::printcompany() 变成 CPerson::printcompany() const 的形式就好了
最终代码:
class CPerson
{
public:
CPerson(string name):m_name(name)
{
}
virtual ~CPerson()
{
}
void printname()
{
cout << m_name << endl;
}
void printcompany( string strcompany) const
{
cout << m_name << " " << strcompany << endl;
}
private:
string m_name;
};
int _tmain(int argc, _TCHAR* argv[])
{
CPerson p1("tom");
CPerson p2("jerry");
vector <CPerson> vecperson;
vecperson.push_back(p1);
vecperson.push_back(p2);
for_each(vecperson.begin(), vecperson.end(), mem_fun_ref(&CPerson::printname));
for_each(vecperson.begin(), vecperson.end(), bind2nd(mem_fun_ref(&CPerson::printcompany), "abc") );
//
// mem_fun
//
CPerson * pp1 = &p1;
CPerson * pp2 = &p2;
vector <CPerson*> vecpersonptr;
vecpersonptr.push_back(pp1);
vecpersonptr.push_back(pp2);
for_each(vecpersonptr.begin(), vecpersonptr.end(), mem_fun(&CPerson::printname));
for_each(vecpersonptr.begin(), vecpersonptr.end(), bind2nd(mem_fun(&CPerson::printcompany), "abc") );
vector <string> vecstring;
vecstring.push_back("abc");
vecstring.push_back("def");
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun(&CPerson::printcompany), pp1) );
for_each(vecstring.begin(), vecstring.end(), bind1st(mem_fun_ref(&CPerson::printcompany), p1) );
return 0;
}
参考:
http://www.cppblog.com/Young/archive/2011/01/09/138199.html
ptr_fun的使用
ptr_fun是将一个普通的函数适配成一个functor,添加上argument type和result type等类型, 其实现如下(例子里面是binary_function,unary_function同理):
- template<class _Arg1,
- class _Arg2,
- class _Result> inline
- pointer_to_binary_function<_Arg1, _Arg2, _Result,
- _Result(__fastcall *)(_Arg1, _Arg2)>
- ptr_fun(_Result (__fastcall *_Left)(_Arg1, _Arg2))
- { // return pointer_to_binary_function functor adapter
- return (std::pointer_to_binary_function<_Arg1, _Arg2, _Result,
- _Result (__fastcall *)(_Arg1, _Arg2)>(_Left));
- }
由上面的代码可见,ptr_fun只是将一个普通的函数(或者函数指针)适配成类pointer_to_binary_function,而该类实际上是binary_function的子类,这样出来的functor就有利于同STL的算法等适配。
下面的例子就是说明了使用ptr_fun将普通的函数适配成bind1st或bind2nd能够使用的functor,否则对bind1st或bind2nd直接绑定普通函数,则编译出错。
- #include <algorithm>
- #include <functional>
- #include <iostream>
- using namespace std;
- int sum(int arg1, int arg2)
- {
- cout<<"ARG 1: "<<arg1<<endl;
- cout<<"ARG 2: "<<arg2<<endl;
- int sum = arg1 + arg2;
- cout<<"SUM: "<<sum<<endl;
- return sum;
- }
- int main(int argc,char* argv[])
- {
- bind1st(ptr_fun(sum),1)(2); // the same as sum(1,2)
- bind2nd(ptr_fun(sum),1)(2); //the same as sum(2,1)
- getchar();
- return 0;
- }