(本节内容未能理解,建议结合STL源码剖析阅读,另外,我还是习惯于使用lambda)
问题实例
假设现有一个存放widget*的list,以及一个判断式判断widget*指向的对象是否有趣:1
2list<Widget*> widgetPtrs;
bool isInteresting(const Widget *pw);
如果我们想要查找第一个有趣的widget,直接调用find_if即可:1
2
3
4auto i = find_if(widgetPtrs.begin(), widgetPtrs.end(),isInteresting);
if (i != widgetPtrs.end()) {
...//i指向了目标对象
}
但问题在于,如果我想要找第一个不有趣的Widget,常规写法遭到了编译失败:1
auto i =find_if(widgetPtrs.begin(), widgetPtrs.end(),not1(isInteresting)); //error
为了保证成功编译与运行,我们必须对判断式使用ptr_fun:1
auto i = find_if(widgetPtrs.begin(), widgetPtrs.end(),not1(ptr_func(isInteresting)));
ptr_fun与适配性
ptr_fun所做的事情就是使一些typedef生效。作为一个低级的函数指针,isInteresting不具备not1所需要的typedef。
四个标准函数适配器(not1,not2,bind1st,bind2nd)都需要存在某些typedef,我们称缺乏typedef的对象不可适配。
这里只提及缺乏typedef但并没有描述那些typedef是什么,这是因为除非你需要设计自己的适配器,否则你都可以通过继承一个base sturct来获得它们。接受一个参数的谓词继承unary_function,两个的则是接受binary_function。
仿函数模板类
unary_function
和binary_function
是模板,所以必须要指定模板参数.其继承形式大致如下:1
2
3
4
5
6
7
8
9
10
11
12template<typename T>
class MeetsThreshold: public std::unary_function<Widget, bool>{
private:
const T threshold;
public:
MeetsThreshold(const T& threshold);
bool operator()(const Widget&) const;
...
};
struct WidgetNameCompare:public std::binary_function<Widget, Widget, bool>{
bool operator()(const Widget& lhs, const Widget& rhs) const;
};
可以看出,operator()的返回值被作为了最后一个模板参数。
一般来说,我们习惯于把无状态类记为struct(也许是为了少打那个public),有数据的类则记为class.
可以看到,operator()的参数是const Widget,但给模板的参数却是Widget,你只需要记得这么做就好了。但如果是指针,一定要记住const不能少,模板参数必须和实参一样。
如果给了一个仿函数类多种调用形式,那必然会减少可适配性。