(十五)适配器adapters

适配器简介

  • adapter更像是一个换肤工程,如把参数的个数改一下或者把函数的名称改一下。
  • 适配器根据它所改的对象分为三类
    • 函数适配器
    • 迭代器适配器
    • 容器适配器
  • 适配器更像是一个桥梁,只是修改接口,并不自己实现真正的功能
  • 适配器都是用内含的方式实现对另一个东西的控制

容器适配器stack、queue

  • 二者都内含了一个sequence,默认是deque。将容器的所有接口封装为个别的几个,或者将容器的接口封装后修改其名称
template <class T, class Sequence = deque<T>>
class stack{
...
public:
	typedef typename Sequence::value_type value_type;
	typedef typename Sequence::size_type size_type;
	typedef typename Sequence::reference reference;
	typedef typename Sequence::const_reference const_reference;
protected:
	Sequence c;//底层容器
public:
	bool empty() const{ return c.empty(); }
	size_type size() const { return c.size(); }
	reference top() { return c.back(); }
	const_reference top() const{ return c.back(); }
	void push(const value_type& x) { c.push_back(x); }
	void pop() { c.pop_back(); }
};

函数适配器

binder2nd
  • 将传入的两个参数记下来,被调用时再实现绑定
  • bind已经取代了bind2nd
template<class Operation>
class binder2nd
 : public unary_function<typename Oprtation::first_argument_type, 
						 typename Operation::result_type>{
protected:
	//内部成员,分别记录算式和第二参数
	Operation op;
	typename Operation::second_argument_type value;
public:
	//constructor,将算式和第二参数记录下来
	binder2nd(const Operation& x, const typename Operation::second_argument_type& y):op(x), value(y){ }
	//在实际调用时,使用存起来的第二实参
	typename Operation::result_type
	operator()(const typename Operation::first_argument_type& x) const{
	return op(x, value);
}
};

//辅助函数,让用户得以方便使用binder2nd<Op>
//编译器会自动推断Op的类型(函数模板会自动做实参推导)
template<class Operation, class T>
inline binder2nd<Operation>bind2nd(const Operation& op, const T& x){
	typedef typename Operation::second_argument_typee arg2_type;//起到类型检查的作用
	return binder2nd<Operation>(op, arg2_type(x));//创建一个binder2nd类型的临时对象
}
-------------------------使用-----------------------------
cout<< count_if(vi.begin(), vi.end(), (bind2nd(less<int>(), 40));
not1
//辅助函数,使用户更加方便的使用unary_negate<Pred>
template<class Predicate>
inline unary_negate<Predicate> not1(const Predicate& pred){
	return unary_negate<Predicate>(pred);
}

//去表达式的否定
template<class Predicate>
class unary_negate
	:public unary_function<typename Predicate::argument_type, bool>{
protected:
	Predicate pred;
public:
	explicit unary_negate(const Predicate& x): pred(x){}
	bool operator()(const typename Predicate::argument_type& x) const{
		return !pred(x);
	}
};
bind
  • bind可以绑定
    • functions
    • function objects
    • member functions,_1必须是某个对象的地址
    • data members,_1必需是某个对象的地址
    • 返回一个函数对象的引用
  • bind可以指定模板参数,最多一个,表示的是返回类型

在这里插入图片描述

迭代器适配器

  • 迭代器就是将要改造的东西记下来,然后看如何改造
reverse_iterator
  • 从尾到头的迭代器
reverse_iterator rbegin()
{ return reverse_iterator(end()); }
reverse_iterator rend()
{ return reverse_iterator(begin()); }
template<class Iterator>
class reverse_iterator
{
protected:
	Iterator current;//对应的正向迭代器
public:
//逆向迭代器的五种typedef与对应的正向迭代器相同
	typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
	typedef typename iterator_traits<Iterator>::value_type value_type;
	...
	typedef Iterator iterator_type;//代表正向迭代器
	typedef reverse_iterator<Iterator> 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(current + b);}
};
inserter
  • inserter是创建一块空间存储数据,而不是直接在一个空闲空间中赋值
  • inserter可以实现在list中插入一个list
  • advance是使迭代器前进3个位置
//辅助函数,帮助用户使用insert_iterator
//函数模板有实参推导
template<class Container, class Iterator>
inline insert_iterator<Container>
inserter(Container& x, Iterator i){
	typedef typename Container::iterator iter;
	return insert_iterator<Container>(x, i);
}

//这个适配器将iterator的赋值操作改为插入操作,并将iterator右移一个位置
//实现让用户执行表面上的赋值而实际上的插入操作
template<class Container>
class insert_iterator{
protected:
	Container* container;//底层容器
	typename Container::iterator iter;
public:
	typedef output_iterator_tag iterator_category;//注意类型
	insert_iterator(Container& x, typename Container::iterator i)
	: container(&x(, iterator(i){}

	insert_iterator<Container>&
	operator=(const typename Container::value_type& value){
		iter = container->insert(iter, value);//调用insert
		++iter;//令insert iterator永远随着target移动
		return *this;
	}
};
x适配器:ostream_iterator
  • ostream_iterator不属于这三种迭代器
//ostream_iterator示例
#include<iostreanm>
#include<iterator>
#include<vector>
#include<algorithm>
int main(){
	std::vector<int> myvector;
	for(int i=0; i<10; ++i) myvec.push_back(i*10);

	std::ostream_iterator<int> out_it(std::cout, ",");
	//第一参数绑定为cout,第二参数绑定为字符串,该字符串是分隔符
	std::copy(myvector.begin(), myvector.end(), out_it);
	//将vector输出到ostream_iterator所指的位置上,表示输出到屏幕上
	return 0;
}
//copy的源代码
//观察copy中有哪些操作符作用到了result上,看这些操作符能否重载以实现新的功能
//*、=、++、return四个动作相配合实现将字符输出到屏幕上去
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
	while(first != last){
		*result = *first;
		++result; ++first;
	}
	return result;
}
//ostream_iterator的源代码
template<class T, class charT=char, class traits=char_traits<charT>>
class ostream_iterator:
	public iterator<output_iterator_tag, void, void, void, void>
{
	basic_ostream<charT, traits>* out_stream;//是一个指针
	const charT* delim;//delim表示分隔符
public:
	typedef charT char_type;
	typedef traits traits_type;
	//构造函数
	typedef basic_ostream<charT, traits> ostream_type;
	ostream_iterator(ostream_type& s): out_stream(&s), delim(0) {}
	ostream_iterator(ostream_type& s, const charT* delimiter)
	:out_stream(&s), delim(delimiter){}
	ostream_iterator(const ostream_iterator<T, charT, traits>& x)
	:out_stream(x.out_stream), delim(x.delim){}
	~ostream_iterator(){}
	//重载=
	ostream_iterator<T, charT, traits>& operator=(const T& value){
		*out_stream<<value;//把value放入到cout中
		if(delim!=0) *out_stream<<delim;//如果delim非空,把分隔符放进去
		return *this;
	}
	
	ostream_iterator<T, charT, traits>& operator*(){ return *this;}
	ostream_iterator<T, charT, traits>& operator++(){ return *this;}
	ostream_iterstor<T, charT, traits>& operator++(int){ return *this;}
x适配器:istream_iterator
//istream+iterator示例
#include<iostream>
#include<iterator>

int main()
{
	double value1, value2;
	std::cout<<"Please, insert two values:";
	std::istream_iterator<double> eos;//end-of-stream iterator,表示结束标志
	std::istream_iterator<double> it(std::cin);//stdin iterator
	if(iit != eos) value1 = *iit;
	++iit;//++表示再读入一个数值
	if(iit!=eos) value2 = *iit;

	std::cout<<value1<<"*"<<value2<<"="
			 <<(value1*value2)<<endl;
	return 0;
}
//示例二
istream_iterator<int> iit(cin), eos;//创建两个对象,一个绑定cin,另一个表示结束标志
copy(iit, eos, inserter(c, c.begin()));
//来源端是从iit到eos
//目的端是一个容器c的起点,且被包装为inserter,将赋值动作改为插入动作

//当创建一个iit时,就已经开始读数据了,此时构造函数中已经有++了
//如果在创建iit的函数后输出一句,请开始输入数据,这句话只有在输入第一个数据之后才会出现
template<class InputIterator, class OutputIterator>
OutputIterator copy(InputIteratornfirst, InputIterator result)
{
	while(first != last){
		*result = *first;
		++result; ++first;
	}
	return result;
}
//istream_iterator的源代码
template<class T, class charT=char, class traits = char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator:
public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
	basic_istream<charT, traits>* in_stream;
	T value;
public:
	typedef charT char_type;
	typedef traits traits_type;
	typedef basic_istream<charT, traits> istream_type;
	istream_iterator():in_stream(0){}
	istream_iterator(istream_type& s):in_stream(&s){++*this; }
	istream_iterator(const istream_iterator<T, charT, traits, Distance>& x):in_stream(x.in_stream), value(x.value){}
	~istream_iterator(){}
	const T& operator*() const { return value;}
	const T* operator->() const { return &value;}
	//++要读入数据
	istream_iterator<T, charT, traits, Distance>& operator++(){
		if(in_stream&& !(*in_stream>>value)) in_stream = 0;
		return *this;
	}
	istream_iterator<T, charT, traits, Distance> operator++(int){
		istream_iterator<T, charT, traits, Distance> tmp = *this;
		++*this;
		return tmp;
	}
};
  • 模板写错一行代码,可能会出现成千上百的错误
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值