データ指向とアルゴリズム指向
(ここで書いている「データ指向」と「アルゴリズム指向」という言葉・観点は私が独自に導入した言葉です.)
STL が強力なライブラリである理由として,アルゴリズムがデータ構造へアクセスする際にそのアクセスがイテレータによって間接化されているからだ,という説明が良くなされる.
ここでさらに一歩進めて,イテレータというのは何らかのデータの列を取得する方法を抽象化したものだ,と考えてみる.コンテナのイテレータは,あるコンテナが保持するデータを列挙するものだが,それはあくまでデータの列挙の1カテゴリに過ぎない,と考えるのである.
今,例えば0から9までの10個の整数データを列挙する,という状況を考えてみる.1つのやり方は,0から9までの整数を保持しているコンテナを生成して,そのコンテナの要素を渡るイテレータを使えばよい.

std::vector< int > v;
for( int i = 0; i < 10; ++i ){
  v.push_back( i );
}

もはやそこに 0 から 10 までの数字で構成されるコンテナ(データ)は存在しない.
イテレータはデータ構造の抽象化ばかりでなく,データ構造の存在それ自体の抽象化をも可能にすると考えられる.すなわち,イテレータの dereference の結果得られているデータが,単にコンテナを渡った結果として得られているのか, algorithmic に生成された結果得られたのか,アルゴリズムは知ることができないし知る必要がない.
このようにイテレータがデータの生成のあり方として,データの列を単に渡っているだけなのか,イテレータの中に組み込まれた何らかのアルゴリズム的要素によって生成されているのか,という2つのあり方が考えられる.ここで,前者のようなデータの取り出しのあり方を「データ指向」と呼び,後者のようなデータの取り出しのあり方を「アルゴリズム指向」と呼ぶことにする.
これは空間消費と時間消費のトレードオフの観点などから良く論じられるもので,その観点自体に目新しいものはない.ここで主張したいのは, STL におけるイテレータによる抽象化がこの2つのあり方をも吸収しえる,ということである.
イテレータのインタフェースは,最も基本的なセットでは「同値性の比較」と「前に進む」と「値を取り出す」という3つの操作しか提供していない.一見するとこの程度のインタフェースのセットで提供,内包できる機能は非常に限定されたもののように思われる.しかし,この非常に小さなインタフェースの中に組み込める機能は,恐らく多くの人が考える以上に表現力豊かで強力である.

std::unique_copy( v.begin(), v.end(), std::back_inserter( tmp ) );
std::count( tmp.begin(), tmp.end(), boost::lambda::_1 % 2 == 0 );

std::count( unique_iterator( v.begin(), v.end() )
          , unique_iterator( v.end(), v.end() )
          , boost::lambda::_1 % 2 == 0 );

イテレータによって吸収されている差異は,データ構造の違いではなく,データがデータ指向に生成されたかアルゴリズム指向で生成されたかの差異である.
これは STL潜在的に持ちえる(しかし一般にほとんど論じられることのない)もう1つの強力な1面と考える.
STL と同様な設計によるライブラリである Boost.Graph でもう1つ例を挙げておく. Boost.Graph では STL で採用されているようなイテレータによる抽象化に加えて,記述子 (descriptor)
今,完全グラフを表現するクラスを作るとする.上で書いた「データ指向」による完全グラフの表現では,完全グラフクラスは N 個の頂点オブジェクトと (N^2 - N) / 2 個の辺オブジェクトを持ったクラスとして表現できるだろう.一方,

class complete_graph
{
private:
  unsigned num_vertices_;
};