LoginSignup
10
8

More than 5 years have passed since last update.

[c++,boost] Eric Niebler's range 3.0の基本設計思想

Posted at

概要

Boost Range 2.0の作者であるEric Nieblerが range 3.0を継続的に開発している(github)。
Ericによるとrange3.0はC++標準規格入りを目指している。

最近の彼のブログポストによると、Range3.0に大きな変更が入ったらしいので、この機に解説してみる。

ほとんどの内容は彼のブログポストとgithub内のドキュメント、特にC++標準規格へのプロポーザルに依っている。

Rangeの基本設計思想

EricはRangeをC++用に設計するに当たって、いくつかの例、特にD言語のRangeに注目し、その改善すべき点を見いだした。

D言語の最も簡単なRangeは基本的には次のメンバ関数から成る。
front()
empty()
pop()
それぞれの意味は推して図るべし。

重要な事は、D言語のRangeは要素の取り出しやRange範囲の操作はできるが、Rangeの"場所"を参照できない。
Ericは、上に述べた理由から、D言語のRangeはいくつかのアルゴリズムの計算オーダーが大きくなってしまっていると述べている(参照)。
そのために、D言語のRangeを使ってC++のIteratorを同じ計算量を保ったまま実装する事は出来ないとしている(逆はできる)。

以上に述べた理由から、EricはRangeに"場所"の情報を持たせるべきだとした。
現在までのC++について考えると、最も簡単で、後方互換性のあるRangeの作り方はIteratorのbegin/endペアをRangeとする事である。
実際、Boost Range2.0ではネイティブにRangeを作る方法が無い場合はboost::make_iterator_rangeを使ってRangeを作っている。

また、他のRangeの実装として、beginとRangeのサイズのペアや、beginとRangeが空である事を判定するPredicateのペア等があり得る。
Ericはこれらの実装も含めて抽象化すべきだと判断した。
理由はその方が速いコンテナ(Ericはdeque等を挙げている)があるためだ。
また、その様な抽象化したレイヤーでアルゴリズムを実装しても、パフォーマンスが劣化しない事をEricは確認している

この様な"場所"の情報を持ったRangeの抽象化のために、Ericはbegin/endのIterator/Iterator対の代わりに、Iterator/Sentinel対という考え方を持ち出した。
この考え方の元では、例えば従来のIteratorのbegin/endペアによるRangeの実装は
Iterator = 従来のIterator
Sentinel = 従来のIterator
となり、beginとRangeのサイズのペアでは
Iterator = 従来のIterator + カウンターのラッパー
Sentinel = 空
となる。

まとめ
Rangeは"場所"の情報も持つ。
Iterator/Sentinel対で実装する。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8