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