トップページ > コンテナとイテレータ >
#include <iostream>
#include <algorithm>
#include <boost/iterator_adaptors.hpp>
using namespace std;
using namespace boost;
struct MyLinkedList
{
// よくある、単方向リンクリストの定義です...
MyLinkedList* next;
int data;
MyLinkedList( MyLinkedList* n, int d )
: next(n), data(d) {}
// ...ここまでは。
public:
struct iterator
: iterator_adaptor<
iterator,
MyLinkedList*, // この型をベースに
int, // この型を返す
forward_traversal_tag // forward_iteratorが欲しい。
>
{
iterator( MyLinkedList* p )
: iterator_adaptor<iterator,
MyLinkedList*,int,forward_traversal_tag>( p ) {}
void increment() { base_reference() = base()->next; }
int& dereference() const { return base_reference()->data; }
};
// begin, end のいい加減な定義
iterator begin(){ return iterator(this); }
iterator end() { return iterator(NULL); }
};
void print(int x)
{
cout << x << endl;
}
int main()
{
// 100->200->300->400->500->600->end。
MyLinkedList f( NULL, 600 );
MyLinkedList e( &f , 500 );
MyLinkedList d( &e , 400 );
MyLinkedList c( &d , 300 );
MyLinkedList b( &c , 200 );
MyLinkedList a( &b , 100 );
// さっき作ったイテレータを使ってみる。
for_each( a.begin(), a.end(), print );
return 0;
}
100 200 300 400 500 600
上の例のように、例えば increment 関数と dereference
関数を決めておいて iterator_adoptor
に入れると、
あとは中で適当によきにはからって、イテレータとして使える構造体
(++
できたり*
できたり、value_type
がtypedef
してあったり)を作りあげてくれるわけです。
単に普通に普通のイテレータを作るだけでなく、例えばdereference
の
返値を base()->data + 10;
にすれば、
10ずれた値を返すような変形イテレータが完成するなどもOK。
まぁ確かに10が足せてもあまり意味はありませんが、色んな物が、
イテレータ化しておくと標準アルゴリズムを使えるようになって便利になることは
ostream_iterator
などの例からも想像がつく気がします。
このライブラリは、incremente,decrement,equal,dereference,…
などの必要な関数を実装すると一からイテレータを作り上げてくれる
iterator_facade
と、既存のイテレータをベースに
iterator_facadeを勝手に実装してくれて、
それを微調整する形で新しいイテレータを作るための iterator_adaptor
、
そしてこの二つを使って作った具体的な汎用イテレータが幾つか、
という構成になっています。
この iterator_adaptors
を使って作れる汎用のイテレータが、
既にヘッダの中に幾つか用意されています。その部分に関してはこちら。