代码改变世界

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

clip_image002

下面是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:

clip_image004

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;

}

};

clip_image006

下面是一个使用stream和stream iterator,应用到算法中是例子

clip_image008

每次istream iterator的++操作都会引发一个read操作,而read操作会将值写入到value中,然后通过*操作返回这个值给result,这样循环后就可以成功从绑定的流中读取到数据,而且时使用iterator的方法

clip_image010

 

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)

clip_image012

………

clip_image014

下面是STL提高的adapter的完整实例过程,关键时可以提供一个functor来辅助算法的实现

clip_image016

//下面介绍源码:

一 对返回值进行逻辑否定: 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);

}

clip_image018

二 对参数进行绑定: 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));

}

//初始化时指定操作和绑定第一个参数,然后就可以像使用仿函数一样传入第二个参数

clip_image020

clip_image022

三 用于函数的合成

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的参数

clip_image024

四 用于函数指针 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);

}

clip_image026

五 用于成员

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表示类内部的成员函数地址,作为参数传入,记录该成员函数。

clip_image028

clip_image030

clip_image032 clip_image034

至此STL源码剖析学习系列结束,原书STL源码剖析中还有一章关于算法的,这里没有描述,有时间再补充。