とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

番兵を持つイテレータアダプタ書いてる (3)

ポインタであればヌルポを使えるのですが,一般的なイテレータんにはヌルポにあたる物が無い(比較可能な無効なイテレータんを提供する要求がない)ようなので is_end_ というフラグで,end か否かを判断するようにしています。
ポインタの時には特殊化してヌルポ使うようにして,is_end_ を定義しないようにすれば,サイズを節約できそうですが,そこまでする能力が今のところないので放置…。とりあえずこれで完成ということに。
現在のソースは以下のようになってます。番兵を持つイテレータアダプタ書いてる (2)のコードも動作するようになりました。ちなみに operator!= が狂気なのは strlen よりできる限り速くするためです。

#include<iterator>
template<typename Iterator,
         typename std::iterator_traits<Iterator>::value_type Sentinel =
          typename std::iterator_traits<Iterator>::value_type()>
 class sentinel_iterator
{
public:
 typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
 typedef typename std::forward_iterator_tag iterator_category;
 typedef typename std::iterator_traits<Iterator>::pointer pointer;
 typedef typename std::iterator_traits<Iterator>::reference reference;
 typedef typename std::iterator_traits<Iterator>::value_type value_type;

private:
 typedef sentinel_iterator<Iterator, Sentinel> self;
 static const value_type sentinel_ = Sentinel;
 Iterator iter_;
 bool is_end_;

public:
 // end iterator
 sentinel_iterator()
  : iter_(), is_end_(true)
 {}
 // normal iterator 
 sentinel_iterator(const Iterator& iter)
  : iter_(iter), is_end_(*iter == sentinel_ ? true : false)
 {}
 reference operator*()
 {
  return *iter_;
 }
 self& operator++()
 {
  ++iter_;
  if(*iter_ == sentinel_)is_end_ = true;
  return *this;
 }
 self operator++(int)
 {
  const self tmp = *this;
  ++(*this);
  return tmp;
 }
 bool operator==(const self& rhs)const
 {
  return !(*this != rhs);
 }
 bool operator!=(const self& rhs)const
 {
  return (!is_end_ || !rhs.is_end_)
   && (is_end_ || rhs.is_end_ || !(iter_ == rhs.iter_));
 }
};