适配器 adapter
也可以叫做改造器,改造已经存在的东西
有:仿函数适配器、迭代器适配器、容器适配器
实现适配,可以使用继承、复合的两种方式实现。
共性:STL使用复合来实现适配
容器适配器
包括stack、queue,内含一个容器,这样也算一种改造
仿函数适配器
bind2nd
可以看到下面的这个例子,使用算法count_if,其中第三个参数是一个predicate,也就是判断雕件,有一个仿函数对象less<int>(),但是他被仿函数适配器bind2nd(将less的第二个参数帮定位40)和not1(取反)修饰,从而实现判断条件为是否小于40。
bind2nd调用binder2nd。
图上灰色的东西就是仿函数适配器和仿函数之间的问答!这里就体现了仿函数为什么要继承适合的unary_function或者binary_function等类的原因!
还有一个细节:适配器适配之后的仿函数也能够继续被适配,所以适配器要继承unary_function或者binary_function等类,这样才能回答另外一个适配器的问题。
所以,仿函数必须能够回答适配器的问题,这个仿函数才是可适配的!
bind
可以绑定:
functions
function objects
member functions, _1必须是某个object的地址
data members, _1必须是某个object的地址
返回一个function object ret。调用ret相当于调用上述的1,2,3或者相当于取出4.
double my_divide(double x, double y){
return x / y;
}
---------------------绑定function,也就是前面的1---------------------
// 占位符的使用方法!!!!!!!!
using namespace std::placeholder;
auto fn_five = bind(my_divide, 10, 2);
cout << fn_five() << endl;// 输出5
auto fn_five = bind(my_divide, _1, 2);
cout << fn_five(10) << endl;// 输出5
auto fn_five = bind(my_divide, _2, _1);
cout << fn_five(10, 2) << endl;// 输出0.2
auto fn_five = bind<int>(my_divide, _2, _1);
cout << fn_five(10, 2) << endl;// 输出0,因为指定了返回类型
---------------------绑定member functions,也就是前面的3---------------------
struct MyPair{
double a,b;
double multiply(){ return a * b; }
}
Mypair ten_two { 10, 2 };
//member function其实有一个this指针
auto bound_menfn = bind(&MyPair::multiply, _1);
cout << bound_menfn(ten_two) << endl;// 输出20
---------------------绑定member data,也就是前面的4---------------------
auto bound_mendata = bind(&MyPair::a, ten_two);
cout << bound_mendata() << endl;// 输出10
auto bound_mendata = bind(&MyPair::b, _1);
cout << bound_mendata(ten_two) << endl;// 输出2
迭代器适配器
reverse_iterator
reverse_iterator
rbegin(){
return reverse_iterator(end());
}
reverse_iterator
rend(){
return reverse_iterator(begin());
}
inserter
可以不用担心copy到的目的容器大小不匹配的问题。
我们调用copy,希望完成在容器指定位置插入一些值,但是需要改变已经写好的copy的功能。
可以通过运算符重载来实现。把相应的容器和迭代器传入 inserter
因为这个是对迭代器的=运算符行为进行重定义,所以是迭代器的适配器。
X适配器: ostream_iterator istream_iterator
ostream_iterator
适配的是basic_ostream,也是重载=运算符,添加输出操作。
istream_iterator
cin>>x被替换为了x=*iit,适配basic_istream
参考书籍:《STL源码剖析》
参考文章:侯捷C++八部曲笔记(二、STL标准库和泛型编程)_侯捷stl-CSDN博客