酒店设计网站推荐,成都品牌网站建设,杭州免费网站制作,wordpress 3.5.18 适配器 
适配器 Adapter 只是一个小变化#xff0c;比如改个接口#xff0c;函数名称等等其出现在三个地方#xff1a;仿函数适配器#xff0c;迭代器适配器#xff0c;容器适配器可以使用继承 / 复合的两种方式实现#xff0c;STL中都用复合 其思想就是将该记的东西记…8 适配器 
适配器 Adapter 只是一个小变化比如改个接口函数名称等等其出现在三个地方仿函数适配器迭代器适配器容器适配器可以使用继承 / 复合的两种方式实现STL中都用复合 其思想就是将该记的东西记起来以便日后使用 8.1 容器适配器 
stackqueue 都是属于 deque 的 Adapter 
比如 stack 中将 deque 的 push_back 改名为 push 
8.2 函数适配器 
8.2.1 binder2nd 
binder2nd —— 绑定第二参数 
// 数范围内所有小于40的元素个数
cout  count_if(vi.begin(), vi.end(), bind2nd(lessint(), 40));// 辅助函数bind2nd使用方便
// 编译器自动推动op的类型函数模板
template class Operation, class T
inline binder2ndOperation bind2nd(const Operation op, const T x)
{typedef typename Operation::second_argument_type arg2_type;// 调用ctor生成一个binder2nd临时对象并返回return binder2ndOperation(op, arg2_type(x)); 
}// binder2nd适配器将二元函数对象转换为一元函数对象
template class Operation
class binder2nd : public unary_functiontypename Operation::first_argument_type,typename Operation::result_type
// 可能binder2nd也要被改造要回答问题
{
protected:Operation op; // 内部成员记录op和第二实参typename Operation::second_argument_type value;
public:binder2nd(const Operation x, const typename Operation::second_argument_type y): op(x), value(y) {} // ctor将op和第二实参记录下来typename Operation::result_typeoperator()(const typename Operation::first_argument_type x) const{return op(x, value); // 实际调用op第二实参为value}
};当然还有binder1st —— 绑定第二参数 
新型适配器bind代替了 bind1stbind2ndbinder1stbinder2nd 
8.2.2 not1 
not1 —— 否定 
// 数范围内所有大于等于40的元素个数
cout  count_if(vi.begin(), vi.end(), not1(bind2nd(lessint(), 40)));8.2.3 bind 
C11提供的 Adapter其可以绑定 
functionsfunction objectsmember functionsdata members 
测试函数 / 对象 
// functions
double my_divide(double x, double y)
{return x/y;
}// function objects 测试与functions同理
// dividesdouble my_divide;struct MyPair
{// data membersdouble a, b;// member functionsdouble multiply(){return a*b;}
};占位符 placeholders using namespace std::placeholders; 提供了 _1_2_3······· 下面的的 _1 指的是被绑函数中的第一个参数 binding functions / function objects 测试  单纯将两个整数 102 绑定到 my_divide auto fn_five  bind(my_divide, 10, 2);
cout  fn_five()  endl; // 5.0用 _1 占据第一参数第二参数绑定2即 x/2 auto fn_half  bind(my_divide, _1, 2);
cout  fn_half(10)  endl; // 5.0用 _1 占据第一参数_2 占据第二参数即 y/x auto fn_invert  bind(my_divide, _2, _1);
cout  fn_invert(10, 2)  endl; // 0.2给 bind 指定了一个模板参数 int将 my_divide 的返回类型变为 int即 int(x/y) auto fn_rounding  bindint(my_divide, _1, _2);
cout  fn_rounding(10, 3)  endl; // 3binding member functions / data members 测试 MyPair ten_two {10, 2}; 用C11的新语法定义一个实例  绑定 member functions由于成员函数有 this所以 _1 就相当于 this即 x.multiply() auto bound_memfn  bind(MyPair::multiply, _1);
cout  bound_memfn(ten_two)  endl; // 20绑定 data members绑定是谁的数据 把实例 ten_two 绑定到 a即 ten_two.a auto bound_memdata  bind(MyPair::a, ten_two);
cout  bound_memdata()  endl; // 10用占位符绑定即 x.a auto bound_member_data2  bind(MyPair::b, _1);
cout  bound_member_data2(ten_two)  endl;8.3 迭代器适配器 
8.3.1 reverse_iterator 注意对逆向迭代器取值就是取其所指正向迭代器的前一个位置 template class Iterator
class reverse_iterator
{
protected:Iterator current;
public:// 五个associated types与对应的正向迭代器相同typedef Iterator iterator_type; // 代表正向迭代器typedef reverse_iteratorIterator self; // 代表逆向迭代器
public:explicit reverse_iterator(iterator_type x) : current(x) {}reverse_iterator(const self x) : current(x.current) {}iterator_type base() const { return current; } // 取出正向迭代器// 对逆向迭代器取值就是取其所指正向迭代器的前一个位置reference operator*() const { Iterator tmp  current; return *--tmp; }pointer operator-() const { return (operator*()); } // 同上// 前进变后退后退变前进self operator(){ --current; return *this; }self operator--(){ current; return *this; }self operator(difference_type n)const{ return self(current-n); }self operator-(difference_type n)const{ return self(currentn); }
};8.3.2 inserter 
对于 copy(InputIterator first, InputIterator last, OutputIterator result)其会不管 OutputIterator 后是否有充裕空间对 result 开始依次赋值 
但如果使用 inserter就会有如下用 copy 实现的插入的效果 listint foo, bar;
for (int i  1; i  5; i)
{foo.push_back(i);bar.push_back(i*10);
}listint::iterator it  foo.begin();
advance(it, 3);copy(bar.begin(), bar.end(), inserter(foo, it));注其是 output_iterator_tag 其实现原理核心就是 —— 对  的操作符重载 
insert_iteratorContainer
operator(const typename Container::value_type val)
{// 关键转调用insert()iter  container-insert(iter, val);iter; // 使其一直随target贴身移动return *this;
}8.4 X适配器 
8.4.1 ostream_iterator 
其会将 copy 变为一个输出工具分隔符是 , 
vectorint vec  { 1,2,3,4,5,6,7,8,9,10 };ostream_iteratorint out_it(cout, ,);
copy(vec.begin(), vec.end(), out_it); // 1,2,3,4,5,6,7,8,9,10,其核心依然是操作符重载这样就相当于 cout*first; cout,; 
basic_ostreamcharT,traits* out_stream;
const charT* delim;...ostream_iteratorT, charT, traits operator(const T value)
{*out_stream  value;if(delim!0) *out_stream  delim; // 分隔符delimiterreturn *this;
}ostream_iteratorT,charT,traits operator*(){return *this;}
ostream_iteratorT,charT,traits operator(){return *this;}...其中 out_stream 存的 coutdelim 存的 , 
8.4.2 istream_iterator 
例一 
在创建 iit 的时候就已经把所有的键盘输入读进去了之后就是一个一个取出来赋值给 value 的操作 
double value1, value2;
istream_iteratordouble eos; // end of stream iterator
istream_iteratordouble iit(cin); // 相当于cinvalue
if(iit ! eos)value1  *iit; // 相当于return value
iit; // 迭代器不断就是不断地读内容
if(iit ! eos)value2  *iit;例二 
从 cin 读 data插入到目的容器 
istream_iteratordouble eos; // end of stream iterator
istream_iteratordouble iit(cin);copy(iit, eos, inserter(c,c.begin()));原理依旧是大量的**操作符重载 **—— 就可以改变原函数的作用 
basic_istreamcharT, traits* in_stream;
T value;...istream_iterator():in_stream(0){} // eos
istream_iterator(istream_type s):in_stream(s){*this;} // 进istream_iteratorT,charT,traits,Distance operator()
{if(in_stream  !(*in_stream  value)) // 开始读了in_stream  0;return *this;
}
const T operator*() const { return value; }...