STL源码剖析之container,stream,functor Adapter
2011-07-02 13:44 Aga.J 阅读(839) 评论(0) 编辑 收藏 举报6 container adapter
Stack是一个container adapter,它封装了所有的deque对外接口,只开放符合stack原则的几个函数,从stack的定义中我们可以看到,它是使用deque作为底层逻辑结构,封装其接口来暴露自身接口
Template<class T, class Sequence=deque<T> >
Class stack
{
Protected:
Sequence c;
};
Queue也是同样的道理
Template< class T, class Sequence = deque<T> >
Class queue
{
Protected:
Sequence c;
};
7 iterator adapter
Insert iterator: 每个insert iterator内部都会维护一个容器,容器内部也有属于自己的迭代器,当客户对insert iterator做赋值assign操作的时候,就在insert iterator中被转为对该容器的迭代器做插入insert的操作,也就是说,在insert iterator的operator=操作符会调用底层容器的push_front或push_back或insert。而其他迭代器操作++,*都会被关闭。所以insert指针进行插入,无法进行前进,后退,取值等操作
Template<class Container>
Class back_insert_iterator
{
Protected:
Container* container; //底层容器
Public:
Typedef output_iterator_tag iterator_categoty;
Typedef void value_type;
Typedef void difference_type;
Typedef void pointer;
Typedef void reference;
Explicit back_insert_iterator(Container& x) : container(&x){}
back_insert_iterator<Container>& operator=( const typename Container::value_tyep& value)
{
Container->push_back( value );
Return *this;
}
//下面的操作不起作用
Back_insert_iterator<Container>& operator*() {return *this;}
Back_insert_iterator<Container>& operator++(){return *this;}
Back_insert_iterator<Container>& operator++(int){return *this;}
};
Front_insert_iterator和insert_iterator的类定义也类似
Reverse iterator: 将迭代器的移动行为倒转,例如
Copy( id.rbegin(), id.rend(), ite);
//如果使用的是reverse iterator,那么会将所有元素逆向拷贝到ite所指的位置上去。
//看看在vector中 rbegin和rend的定义
Template< class T, class Alloc=alloc>
Class Vector
{
Public:
Typedef T value_type;
Typedef value_type* iterator;
Typedef reverse_iterator<iterator> reverse_iterator;
//reverse_iterator模板类接受的是一个迭代器
Reverse_iterator rbegin(){return reverse_iterator( end() );}
//借助reverse_iterator构造函数,传入普通迭代器,来获取一个reverse迭代器
Reverse_iterator rend() {return reverse_iterator( begin() );}
};
其他双向序列容器 只要提供了begin和end,那么它的rbegin和rend就会类似于上述情况。
而单向序列容器不可以使用reserve iterator,有些容器stack等没有提供begin也不能使用rbegin
下面是reverse_iterator的源码
Template< class Iterator>
Class reverse_iterator
{
Protected:
Iterator current;
Public:
Typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
Typedef typename iterator_traits<Iterator>::value_type value_type;
Typedef typename iterator_traits<Iterator>::difference_type difference_type;
Typedef typename iterator_traits<Iterator>::pointer pointer;
Typedef typename iterator_traits<Iterator>::reference reference;
Typedef Iterator iterator_type;
Typedef reverse_iterator<Iterator> self;
Public:
Reverse_iterator(){}
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;
returtn *--tmp;
}
Pointer operator->() const {return &(operator*());}
Self& operator++()
{
--current;
Return *this;
}
Self& operator++(int)
{
Self tmp=*this;
--current;
Return tmp;
}
Self operator+(difference_type n) const
{
Return self( current-n);
}
Self& operator+=(difference_type n)
{
Current -= n;
Return *this;
}
};
Stream iterator:将迭代器绑定到一个stream对象上,例如绑定到istream对象的称为istream _iterator,其实所谓绑定到一个istream 对象,其实就是在istream的iterator内部维护一个istream member,客户端对这个迭代器所做的operator ++等操作,会被导引调用迭代器内部所含的那个istream member的输入操作(>>)
Template< class T, class Distance=ptrdiff_t >
Class istream_iterator
{
Friend bool operator== __STL_NULL_TMPL_ARGS( const istream_iterator<T,Distance>&x, const istream_iterator<T,Distance>&y);
Protected:
Istream* stream;
T value;
Bool end_marker;
Void read()
{
End_marker=(*stream) ? true: false;
If( end_marker ) *stream>>value; //关键在这里
//输入后,stream的状态可能改变,所以下面再判断一次决定end_marker
//当读到eof或者类型不符合的资料时,stream处于false
End_maker = (*stream) ? true: false;
}
Public:
Istream_iterator():stream(&s),end_maker(false){}
Istream_iterator( istream& s) : stream(&s){read();}
Reference operator*() const{return value;}
Istream_iterator<T,Distance>& operator++()
//istream iterator的++操作其实就是底层istream的read操作
{
Read();
Return *this;
}
};
下面是一个使用stream和stream iterator,应用到算法中是例子
每次istream iterator的++操作都会引发一个read操作,而read操作会将值写入到value中,然后通过*操作返回这个值给result,这样循环后就可以成功从绑定的流中读取到数据,而且时使用iterator的方法
9 SGI STL的function adaper细节
我们知道
1 容器是以class template完成的
2 算法是以function template完成的
3 仿函数是一种operator()重载的class template
4 迭代器是一种将operator++和operator*等指针习惯常行为重载的class template
5 应用于容器和迭代器身上的adapter也是一种class template
【container adapter内藏一个container member, reverse iterator adapter内藏一个iterator membet, stream iterator adapter 内藏一个point to container】
6 应用与function的adapter内藏一个member object,它的类型等同与它所要配接的对象(例如adaptable functor)
………
下面是STL提高的adapter的完整实例过程,关键时可以提供一个functor来辅助算法的实现
//下面介绍源码:
一 对返回值进行逻辑否定: not1, not2
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);
}
};
Template<class Predicate>
Inline unary_negate<Predicate> not1( const Predicate& pred)
{
Return unary_negate< Predicate>(pred);
}
二 对参数进行绑定: bind1st, bind2nd
Template<class Operation>
Class binder1st: public unary_function<typename Operation::second_argument_type,
Typename Operation::result_type>
{
Protected:
Operation op;
Typename Operation::first_argument_type value;
Public:
Binder1st( const Operation& x, const typename Operation::first_argument_type& y)
:op(x),value(y) {}
Typename Operation::result_type
Operation() ( const typename Operation::second_argument_type& x)const
{ return op(value,x);}
};
Template<class Operation,class T>
Inline binder1st<Operation> bind1st( const Operation& op, const T& x)
{
Typedef typename Operation::first_argument_type arg1_type;
Return binder1st<Operation>( op, arg1_type(x));
}
//初始化时指定操作和绑定第一个参数,然后就可以像使用仿函数一样传入第二个参数
三 用于函数的合成
Template< class Operation1, class Operation2>
Class unary_compose:
Public unary_function<typename Operation2::argument_type,
Typename Operation1::result_type>
{
Protected:
Operation1 op1;
Operation2 op2;
Public:
Unary_compose( const Operation1& x, const Operation2& y)
: op1(x),op2(y){}
Typename Operation1::result_type operation()(consti typename Operation2::argument_type& x)const{return op1(op2(x));}
};
Template<class Operation1, class Operation2>
Inline unary_compse<Operation1,Operation2>
Compose1(const Operation1& op1, const Operation2& op2)
{
Return unary_compose< Operation1, Operation2>(op1,,op2);
}
//初始化传入两个op方法,调用()操作是则使用op2(x)的返回值作为op1的参数
四 用于函数指针 ptr_fun
Template<class Arg, class Result>
Class pointer_to_unary_function:public unary_function<Arg,Result>
{
Protected:
Result (*ptr)(Arg); //内部成员 一个函数指针,返回Result类型,参数为arg
Public:
Pointer_to_unary_function(){}
Explicit pointer_to_unary_function( Result(*x)(arg)):ptr(x){}
Result operation()(Arg x) const{return ptr(x);}
};
Template< class Arg, class Result>
Inline pointer_to_unary_function<Arg,Result>
Ptr_fun(Result(*x) (Arg))
{
Return pointer_to_unary_function<Arg,Result>(x);
}
五 用于成员
Template< class S, class T>
Class mem_fun_t:public unary_funcrtion<T* ,S>
{
Public:
Explicit mem_fun_t (S {T::*pf}()): f(pf){}
S operaton()(T* p)const {return (p->*f)();}
Private:
S (T::*f)();
};
// 知道返回类型S和类类型T,使用T::*p表示类内部的成员函数地址,作为参数传入,记录该成员函数。
至此STL源码剖析学习系列结束,原书STL源码剖析中还有一章关于算法的,这里没有描述,有时间再补充。
作者:Aga.J
出处:http://www.cnblogs.com/aga-j
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
个人学习笔记仅供本人记录知识所用,不属发表性文章。