(个人认为习得lambda后无需理会本节内容)
前言
ptr_fun、mem_fun和mem_fun_ref的主要任务是覆盖C++固有的语法矛盾。
问题实例
当前存在一个函数f与一个对象x,编码环境不处于x的成员函数内,如果需要在x上调用f,则有三种调用方法:1
2
3f(x);//当f是一个非成员函数
x.f();//当f是一个成员函数,并且x是一个对象或一个对象的引用
p->f();//当f是一个成员函数,并且p是一个指向对象的指针
假设有一个测试Widget的函数和一个Widget容器:1
2void test(Widget& w);
vector<Widget> vw;
我们需要测试容器内所有的Widget:1
for_each(vw.begin(), vw.end(), test);
但如果test是一个成员函数,我们似乎可以这样:1
for_each(vw.begin(), vw.end(),&Widget::test);//无法编译
又或者我们还会试图访问指针来执行操作:1
2list<Widget*> lpw;
for_each(lpw.begin(), lpw.end(),&Widget::test);//无法编译
问题剖析
for_each不支持将成员函数作为谓词传入,原因在于for_each的实现:1
2
3
4template<typename InputIterator, typename Function>
Function for_each(InputIterator begin, InputIterator end, Function f){
while (begin != end) f(*begin++);
}
STL算法中函数和函数对象总是使用用于非成员函数的语法形式调用,这也就是mem_fun与mem_fun_ref存在的意义。它们让成员函数得以作为谓词。
mem_fun与mem_fun_ref
它们具体的实现并不复杂,总体来说是一个函数模板,以下是其中的一个声明:1
2
3
4//用于不带参数的non-const成员函数
// C是类,R是被指的成员函数的返回类型
template<typename R, typename C>
mem_fun_t<R,C> mem_fun(R(C::*pmf)());
mem_fun带有一个指向成员函数的指针pmf,并返回一个mem_fun_t类型的对象。这个仿函数类容纳成员函数指针并且提供一个operator()
,它调用指向传给operator()
的对象上的成员函数。
针对Widget那个实例:1
2ist<Widget*> lpw;
for_each(lpw.begin(), lpw.end(),mem_fun(&Widget::test));
for_each接受一个mem_fun_t类型的对象,它持有一个test函数指针,对于lpw里面所有的Widget*指针,for_each使用调用mem_fun_t,随后该对象立刻在Widget*上调用test.
mem_fun_ref效果类似,它们也被称为函数对象适配器。
ptr_fun
ptr_fun增加了一些typedef,如果你不确定啥时候用它,就记得每一次都用它。