天天看點

stl_iterator.h 二

六. istream_iterator

istream_iterator的目的是從輸入流中讀取資料, 疊代器類型:input_iterator_tag. 接收一個輸入流為參數, istream_iterator儲存這個輸入流,并且每次operator++的時候從輸入流中讀取一個資料, operator*取到所讀取資料的值, operator->是取得所讀取資料的引用。  從源碼來看,一個輸入流傳入一個疊代器,沒有問題, 但是如果一個輸入流傳入幾個疊代器, 并且每個疊代器都執行++, 那麼可能輸入流的資料就會遭到嚴重破壞。 是以,使用istream_iterator要小心。 當*_M_stream 為false, 則說明輸入流結束, 可能收到了'/0/字元. 實作:

template <class _Tp,

          class _CharT = char, class _Traits = char_traits<_CharT>,

          class _Dist = ptrdiff_t>

class istream_iterator {

public:

  typedef _CharT                         char_type;

  typedef _Traits                        traits_type;

  typedef basic_istream<_CharT, _Traits> istream_type;

  typedef input_iterator_tag             iterator_category;

  typedef _Tp                            value_type;

  typedef _Dist                          difference_type;

  typedef const _Tp*                     pointer;

  typedef const _Tp&                     reference;

  istream_iterator() : _M_stream(0), _M_ok(false) {}

  istream_iterator(istream_type& __s) : _M_stream(&__s) { _M_read(); }

  reference operator*() const { return _M_value; }

  pointer operator->() const { return &(operator*()); }

  istream_iterator& operator++() {

    _M_read();

    return *this;

  }

  istream_iterator operator++(int)  {

    istream_iterator __tmp = *this;

    _M_read();

    return __tmp;

  }

  bool _M_equal(const istream_iterator& __x) const

    { return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream); }

private:

  istream_type* _M_stream;

  _Tp _M_value;

  bool _M_ok;

  void _M_read() {

    _M_ok = (_M_stream && *_M_stream) ? true : false;

    if (_M_ok) {

      *_M_stream >> _M_value;

      _M_ok = *_M_stream ? true : false;

    }

  }

};

template <class _Tp, class _CharT, class _Traits, class _Dist>

inline bool

operator==(const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __x,

           const istream_iterator<_Tp, _CharT, _Traits, _Dist>& __y) {

  return __x._M_equal(__y);

}

七. ostream_iterator

用途應當是格式化輸入, 疊代器類型output_iterator_tag.  接收一個輸出流作為參數,  輸出疊代器隻需要實作operator=, 其他的幾個操作符都啥也不幹,直接傳回, 實作:

template <class _Tp,

          class _CharT = char, class _Traits = char_traits<_CharT> >

class ostream_iterator {

public:

  typedef _CharT                         char_type;

  typedef _Traits                        traits_type;

  typedef basic_ostream<_CharT, _Traits> ostream_type;

  typedef output_iterator_tag            iterator_category;

  typedef void                           value_type;

  typedef void                           difference_type;

  typedef void                           pointer;

  typedef void                           reference;

  ostream_iterator(ostream_type& __s) : _M_stream(&__s), _M_string(0) {}

  ostream_iterator(ostream_type& __s, const _CharT* __c)

    : _M_stream(&__s), _M_string(__c)  {}

  ostream_iterator<_Tp>& operator=(const _Tp& __value) {

    *_M_stream << __value;

    if (_M_string) *_M_stream << _M_string;

    return *this;

  }

  ostream_iterator<_Tp>& operator*() { return *this; }

  ostream_iterator<_Tp>& operator++() { return *this; }

  ostream_iterator<_Tp>& operator++(int) { return *this; }

private:

  ostream_type* _M_stream;

  const _CharT* _M_string;

};

注意operator=, 當_M_string不為0, 那麼每次向輸出疊代器指派, 輸出疊代器都會首先向輸出流寫值,然後寫_M_string這個格式串, 而達到格式化的目的。

八. istreambuf_iterator

istreambuf_iterator的目的是從basic_streambuf流中讀取資料, 疊代器類型:input_iterator_tag.

 接收一個basic_streambuf流或basic_istream為參數, basic_istream可通過rdbuf()轉為basic_streambuf. 

此外還存儲  streambuf_type* _M_buf;  mutable _CharT _M_c;  mutable bool _M_eof : 1;  mutable bool _M_is_initialized : 1; 這4個成員.

 _M_buf是流的引用,  _M_c是目前讀出來的值,  _M_eof标記流是否結束,  _M_is_initialized标記是否開始. 

除了從中讀取的流是basic_streambuf外,其他和istream_iterator比較相似。 實作的差別主要在于讀取, 這裡相對複雜一些。_M_getc是讀取字元,  _M_nextc是下一個字元。  注意M_equal_aux, _M_dereference_aux。 分别是兩個輔助函數, 用來判等和第一次解引用時調用。 實作:

template<class _CharT, class _Traits>

class istreambuf_iterator

  : public iterator<input_iterator_tag, _CharT,

                    typename _Traits::off_type, _CharT*, _CharT&>

{

public:

  typedef _CharT                           char_type;

  typedef _Traits                          traits_type;

  typedef typename _Traits::int_type       int_type;

  typedef basic_streambuf<_CharT, _Traits> streambuf_type;

  typedef basic_istream<_CharT, _Traits>   istream_type;

public:

  istreambuf_iterator(streambuf_type* __p = 0) { this->_M_init(__p); }

  istreambuf_iterator(istream_type& __is) { this->_M_init(__is.rdbuf()); }

  char_type operator*() const

    { return _M_is_initialized ? _M_c : _M_dereference_aux(); }

  istreambuf_iterator& operator++() { this->_M_nextc(); return *this; }

  istreambuf_iterator  operator++(int) {

    if (!_M_is_initialized)

      _M_postincr_aux();

    istreambuf_iterator __tmp = *this;

    this->_M_nextc();

    return __tmp;

  }

  bool equal(const istreambuf_iterator& __i) const {

    return this->_M_is_initialized && __i._M_is_initialized

      ? this->_M_eof == __i._M_eof

      : this->_M_equal_aux(__i);

  }

private:

  void _M_init(streambuf_type* __p) {

    _M_buf = __p;

    _M_eof = !__p;

    _M_is_initialized = _M_eof;

  }

  char_type _M_dereference_aux() const;

  bool _M_equal_aux(const istreambuf_iterator&) const;

  void _M_postincr_aux();

  void _M_nextc() {

    int_type __c = _M_buf->snextc();

    _M_c = traits_type::to_char_type(__c);   

    _M_eof = traits_type::eq_int_type(__c, traits_type::eof());

    _M_is_initialized = true;

  }

  void _M_getc() const {

    int_type __c = _M_buf->sgetc();

    _M_c = traits_type::to_char_type(__c);

    _M_eof = traits_type::eq_int_type(__c, traits_type::eof());

    _M_is_initialized = true;

  }

private:

  streambuf_type* _M_buf;

  mutable _CharT _M_c;

  mutable bool _M_eof : 1;

  mutable bool _M_is_initialized : 1;

};

template<class _CharT, class _Traits>

_CharT istreambuf_iterator<_CharT, _Traits>::_M_dereference_aux() const

{

  this->_M_getc();

  return _M_c;

}

template<class _CharT, class _Traits>

bool istreambuf_iterator<_CharT, _Traits>

  ::_M_equal_aux(const istreambuf_iterator& __i) const

{

  if (!this->_M_is_initialized)

    this->_M_getc();

  if (!__i._M_is_initialized)

    __i._M_getc();

  return this->_M_eof == __i._M_eof;

}

template<class _CharT, class _Traits>

void istreambuf_iterator<_CharT, _Traits>::_M_postincr_aux()

{

  this->_M_getc();

}

template<class _CharT, class _Traits>

inline bool operator==(const istreambuf_iterator<_CharT, _Traits>& __x,

                       const istreambuf_iterator<_CharT, _Traits>& __y) {

  return __x.equal(__y);

}

九. ostreambuf_iterator

ostreambuf_iterator和ostream_iterator很類似, 隻是接受的參數和輸出的對象不同, 這裡輸出的對象是basic_streambuf. 最重要的函數, 唯一的操作符重載:

  ostreambuf_iterator& operator=(char_type __c) {

    _M_ok = _M_ok && !traits_type::eq_int_type(_M_buf->sputc(__c),

                                               traits_type::eof());

    return *this;

  }