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

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

反復子クラスを定義する。

STL―標準テンプレートライブラリによるC++プログラミング 第2版
計数反復子クラス。++ 演算の回数を数える前方向イテレータ(アダプタ)。
デバッグビルドしているせいか,予想より(本より)多くのコピーが発生しているのが分かる。おもしろい。
追記:b00stのcounting_iterator とは無関係です。

// P247 ex16-01.cpp
#include<string>
#include<iterator>
#include<iostream>
template<typename ForwardIterator>
 class counting_iterator
{
 ForwardIterator current;
 int plus_count;
 std::string name;
 int version;
public:
 typedef counting_iterator<ForwardIterator> self;
 typedef typename std::iterator_traits<ForwardIterator>::value_type      value_type;
 typedef typename std::iterator_traits<ForwardIterator>::reference       reference;
 typedef typename std::iterator_traits<ForwardIterator>::pointer         pointer;
 typedef typename std::iterator_traits<ForwardIterator>::difference_type difference_type;
 typedef std::forward_iterator_tag iterator_category;

 counting_iterator(ForwardIterator first, const std::string& s)
  : current(first), plus_count(0), name(s), version(1)
 {}
 counting_iterator(const self& other)
  : current(other.current), plus_count(other.plus_count), name(other.name),
    version(other.version + 1)
 {
  std::cout << "copying " << name << ", new version is " << version << std::endl;
 }
 counting_iterator()
  : current(), plus_count(0), name("null"), version(0)
 {}
 reference operator*(){
  return *current;
 }
 bool operator==(const self& other)const{
  return current == other.current;
 }
 bool operator!=(const self& other)const{
  return current != other.current;
 }
 self& operator++(){
  ++current;
  ++plus_count;
  return *this;
 }
 self operator++(int){
  self tmp = *this;
  ++(*this);
  return tmp;
 }
 void report(std::ostream& o)const{
  o << "(" << name << ", version " << version << ", "
   << plus_count << " ++operations)" << std::endl;
 }
};

#include<iostream>
#include<algorithm>
int main(){
 using std::cout;
 using std::endl;
 using std::find;
 cout << "Demonstrating a counting iterator class." << endl;
 const int x[] = {12, 4, 3, 7, 17, 9, 11, 6};
 counting_iterator<const int*> i(&x[0], "Curly"), j(&x[0], "Moe"), end(x + 8, "Larry");
 cout << "Traversing array x\n"
  " from i (Curly) to end (Larry)\n";
 while(i != end){
  cout << *i << endl;
  ++i;
 }
 cout << "After the traversal:\n";
 i.report(cout);
 end.report(cout);
 cout << "Assigning j (Moe) to i (Curly)." << endl;
 i = j;
 cout << "Searching the array\n"
  " from i (Moe) to end (Larry)\n"
  " using find\n";
 counting_iterator<const int*> k = find(i, end, 9);
 cout << "After the find:\n";
 k.report(cout);
 i.report(cout);
 end.report(cout);
}

出力例:

Demonstrating a counting iterator class.
Traversing array x
 from i (Curly) to end (Larry)
12
4
3
7
17
9
11
6
After the traversal:
(Curly, version 1, 8 ++operations)
(Larry, version 1, 0 ++operations)
Assigning j (Moe) to i (Curly).
Searching the array
 from i (Moe) to end (Larry)
 using find
copying Larry, new version is 2
copying Moe, new version is 2
copying Larry, new version is 3
copying Moe, new version is 3
copying Larry, new version is 4
copying Moe, new version is 4
copying Larry, new version is 5
copying Moe, new version is 5
copying Moe, new version is 4
copying Moe, new version is 5
After the find:
(Moe, version 5, 5 ++operations)
(Moe, version 1, 0 ++operations)
(Larry, version 1, 0 ++operations)