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

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

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

C言語の文字列の概念の一般化を目指してる。真のイテレータんになれるようにがんばってる途中。まだ問題あるだろうけど以下長いコード。
あ,そうそう,コンセプトチェック使ってみたよー!

#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;
 Iterator iter_;
 static const value_type sentinel_ = Sentinel;

public:
 sentinel_iterator()
  : iter_()
 {}
 sentinel_iterator(const Iterator& iter)
  : iter_(iter && *iter != sentinel_ ? iter : Iterator())
 {}
 ~sentinel_iterator()
 {}
 reference operator*()
 {
  return *iter_;
 }
 self& operator++()
 {
  ++iter_;
  if(*iter_ == sentinel_)iter_ = Iterator();
  return *this;
 }
 self operator++(int)
 {
  const self tmp = *this;
  ++(*this);
  return tmp;
 }
 bool operator==(const self& rhs)const
 {
  return iter_ == rhs.iter_;
 }
 bool operator!=(const self& rhs)const
 {
  return iter_ != rhs.iter_;
 }
};

#include<boost/concept/requires.hpp>
#include<boost/concept_check.hpp>
template<class T>
void concept_check(T t){
 t;
 BOOST_CONCEPT_ASSERT((::boost::InputIterator<T>(t)));
 BOOST_CONCEPT_ASSERT((::boost::ForwardIterator<T>(t)));
}

#include<cassert>
int main(){
 concept_check(sentinel_iterator<const char*>());
 {
  typedef sentinel_iterator<const char*> cstring_iterator;
  const cstring_iterator end;
  {
   const char* data = "abc";
   cstring_iterator iter(data);
   assert(iter != end);
   assert(*iter == 'a');
   assert(*++iter == 'b');
   assert(*++iter == 'c');
   assert(++iter == end);

   const char datum = '\0';
   cstring_iterator len0(&datum); // len0("") と同じ
   assert(len0 == end);

   cstring_iterator null(0);
   assert(null == end );
  }
 }
 {
  typedef sentinel_iterator<const int*, -1> int_sentinel_iterator;
  const int_sentinel_iterator end;
  {
   const int data[] = {0, 1, 2, -1};
   int_sentinel_iterator iter(data);
   assert(iter != end);
   assert(*iter == 0);
   assert(*++iter == 1);
   assert(*++iter == 2);
   assert(++iter == end);

   const int datum = -1;
   int_sentinel_iterator len0(&datum);
   assert(len0 == end);

   int_sentinel_iterator null(0);
   assert(null == end);
  } 
 }
}