D 2.0
About Japanese Translation

Last update Sun Dec 19 23:27:28 2010

std.range

このモジュールは、レンジの有用な操作を定義しています。 いくつかのアイデアは Leonardo Maffi によるものです。

Source:
std/range.d

License:
Boost License 1.0.

Authors:
Andrei Alexandrescu, David Simcha

template isInputRange(R)
R が入力レンジ(Input Range)のとき true を返します。 入力レンジは基本操作 emptypopFrontfront を提供する必要があります。 以下のコードはどんな入力レンジに対してもコンパイルが通ります。

R r;             // レンジオブジェクトを定義できる
if (r.empty) {}  // 空かどうかテストできる
r.popFront;          // 次の要素へ進めることができる
auto h = r.front; // レンジの先頭要素を取り出せる
入力レンジの意味論 (コンパイル時チェックできない性質) としては、 以下があります (r の型が R であるとして):

  • r.empty は、レンジにまだ値が残っているとき、そのときに限り false を返す
  • r.front は、 レンジの現在の先頭要素を返す。値返しまたは参照返しのどちらでもよい。r.front は、仮に r.empty を呼び出したら false を返す状況でのみ使用できる
  • r.popFront は、レンジの指す先頭を一つ次の要素に進める。 r.popFront の呼び出しは、仮に r.empty を呼び出すと false を返す状況でのみ使用できる
void put(R, E)(ref R r, E e);
er に書き出します。 何が行われるかの詳細は二つの型に依存します。R は出力レンジである必要があります。 以下に挙げるように、いくつかのケースがあります。 以下のコード片のうち最初にコンパイルが通るものが実行されます。

コード片 シナリオ
r.put(e); R にメソッド putE を取るものが定義されている
r.put([ e ]); R にメソッド putE[] を取るものが定義されている
r.front = e; r.popFront(); R が入力レンジで、 er.front へ代入可能
for (; !e.empty; e.popFront()) put(r, e.front); レンジ ER にコピー
r(e); R が、例えば E を取るdelegate
r([ e ]); R が、例えば E[] を取る delegate

template isOutputRange(R,E)
RE型の要素を扱う出力レンジ(Output Range)のとき true を返します。 出力レンジは、上に定義した put(r, e) が可能な値のことを言います。

template isForwardRange(R)
R が前進レンジ(Forward Range)のとき true を返します。 前進レンジは、入力レンジの機能に加え、単純にコピーすることで同じ型のレンジの "チェックポイント" を作ることができるものです。 入力レンジだけれど前進レンジではないよくある例としては、ファイルやソケットを読み取りレンジがあります; これらのレンジをコピーしてもストリーム中の位置を保存せず、 ほとんどの場合、ストリーム全体をメモリに置かないための内部バッファを再利用します。 結果として、コピー元とコピー先のどちらのストリームを進めても、 もう一方に影響してしまいます。 以下のコードはどんな前進レンジに対してもコンパイルが通ります。

static assert(isInputRange!(R));
R r1;
R r2 = r1;           // レンジを他へコピーできる
前進レンジの意味論 (コンパイル時チェックできない性質) は、 入力レンジのそれに加え、 レンジオブジェクトのコピーを取ることで バックトラックが可能であることが要求されます。

template isBidirectionalRange(R)
R が双方向レンジ(Bidirectional Range)のとき true を返します。 双方向レンジは、前進レンジの機能に加え基本操作 backpopBack を提供する必要があります。 以下のコードはどんな双方向レンジに対してもコンパイルが通ります。

R r;
static assert(isForwardRange!(R)); // range is an input range
r.popBack;                        // レンジの終端側を一つ縮めることができる
auto t = r.back;                   // レンジの最後の要素を取得できる
双方向レンジの意味論 (コンパイル時チェックできない性質) としては、 以下があります (r の型が R であるとして):

  • r.back がレンジの最後の要素を(値もしくは参照で)返す。 r.back は、仮に r.empty を呼び出したら false を返す状況でのみ使用できる

template isRandomAccessRange(R)
R がランダムアクセスレンジ(Random Access Range)のとき true を返します。 ランダムアクセスレンジは、双方向レンジの機能に加えて基本関数opIndexを提供する有限レンジか、あるいは前進レンジの機能に加えて基本関数opIndexを提供する無限レンジです。 どちらの場合にせよ、length を提供するか無限レンジであるかのいずれかでなければなりません。 以下のコードはどんなランダムアクセスレンジに対してもコンパイルが通ります。

R r;
static assert(isForwardRange!(R)); // 前進レンジである
static assert(isBidirectionalRange!(R) || isInfinite!(R));
                                  // 双方向または無限
auto e = r[1];                    // 添え字アクセス可能
ランダムアクセスレンジの意味論 (コンパイル時チェックできない性質) としては、 以下がります (r の型が R であるとして):
  • r.opIndex(n) がレンジの n番目の要素への参照を返す

template hasMobileElements(R)
レンジが moveFront プリミティブと、 双方向あるいはランダムアクセスレンジなら更に moveBackmoveAt をサポートするとき、true となります。これらは明示的に実装されることも、 モジュール関数 moveFront その他のデフォルト実装が使われることもあります。

template ElementType(R)
R の要素の型。R は必ずしもレンジでなくとも良い。 要素の型は、型 R のオブジェクト r に対する r.front の結果で決まります。例えば、ElementType!(T[])T です。
template hasSwappableElements(R)
R が前進レンジでswap可能な要素型を持つときに true を返します。 以下のコードはどんなランダムアクセスレンジに対してもコンパイルが通ります。

R r;
static assert(isForwardRange!(R));  // 前進レンジである
swap(r.front, r.front);              // レンジの要素をswap可能

template hasAssignableElements(R)
R が前進レンジで代入可能な要素型を持つときに true を返します。 以下のコードはどんなランダムアクセスレンジに対してもコンパイルが通ります。

R r;
static assert(isForwardRange!(R));  // 前進レンジである
auto e = r.front;
r.front = e;                         // 要素に代入が可能

template hasLvalueElements(R)
R が左辺値要素を持つかどうかをチェックします。 左辺値要素とは、参照渡しが行われ、アドレスが取れる要素のことをいいます。

template hasLength(R)
R が、整数型の値を返す length メンバを持っているときに true を返します。 R は必ずしもレンジでなくても構いません。注意点として、length はオプション的な基本操作で、どのレンジもこれを実装することは必須ではありません。 レンジによっては明示的に長さを保持しない実装もありえますし、 実際にレンジの端まで行かなければ終端のわからないレンジ (ソケットストリーム等) もあり、 さらに無限の長さをもつレンジもあり得ます。

template isInfinite(Range)
無限入力レンジに対して true を返します。 無限入力レンジは、 静的に定義された常に false となる empty メンバを持ちます。 example:
struct InfiniteRange
{
    enum bool empty = false;
    ...
}

template hasSlicing(Range)
Range が整数を指定するスライス演算子を持ち、 入力レンジを返す時に、true となります。 以下のコードは hasSlicingtrue の時にコンパイルが通ります:

Range r;
auto s = r[1 .. 2];
static assert(isInputRange!(typeof(s)));

size_t walkLength(Range)(Range range, size_t upTo = size_t.max);
任意のレンジに適用できる、 ベストエフォート型の length の実装です。

hasLength!(Range) が true ならば、単に range.length を返し、upTo は無視します。

そうでなければ、レンジを先頭から順に読んでいき、 見つかった要素数を返します。Ο(n) 回の range.emptyrange.popFront の呼び出し(ただし nrange の実際の長さ)を行います。upTo パラメタは、 レンジの長さが最低いくつか以上であるかどうかだけに興味があるようなケースに役立ちます。 パラメタ upTo が指定されていれば、upTo ステップ進んだ時点で計算を止め、upTo を返します。

struct Retro(Range) if (isBidirectionalRange!(Unqual!(Range)) && !isRetro!(Range));
Retro!(R) retro(R)(R input);
双方向レンジを逆向きにたどります。

Example:
int[] a = [ 1, 2, 3, 4, 5 ];
assert(equal(retro(a), [ 5, 4, 3, 2, 1 ][]));

bool empty();
input.empty へと転送されます
Retro save();
this のコピーを返します。

void popFront();
input.popBack へと転送されます
ElementType!(R) moveFront();
moveBack(input) へと転送されます

void popBack();
input.popFront へと転送されます
ElementType!(R) moveBack();
moveFront(input) へと転送されます。

front(ElementType!(R) val);
代入サポート

back(ElementType!(R) val);
代入サポート

opIndex(size_t n);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length がある場合に限り定義されます。

void opIndexAssign(ElementType!(R) val, size_t n);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length がある場合に限り定義されます。

ElementType!(R) moveAt(size_t index);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length がある場合に限り定義されます。

typeof(this) opSlice(size_t a, size_t b);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length がある場合に限り定義されます。

size_t length();
レンジの長さを返す基本操作です。 input.length に転送されるため、hasLength!(R) が真なときにのみ定義されます。
struct Stride(Range) if (isInputRange!(Unqual!(Range)));
Stride!(R) stride(R)(R input, size_t n);
レンジ r をストライド n でアクセスします。 ランダムアクセスレンジならば、添え字アクセスによってレンジ上を動きます。 そうでなければ、popFront を必要な回数呼び出して動作します。

Example:
int[] a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
assert(equal(stride(a, 3), [ 1, 4, 7, 10 ][]));

this(R input, size_t n);
ストライドを初期化
Stride save();
this を返します。
bool empty;
input.empty へと転送されます。
ElementType!(R) moveFront();
moveFront(input) へと転送されます。

void popFront();
@@@

void popBack();
input.popBack へと転送されます

back();
余分な要素を除いた後 input.back へと転送されます。
ElementType!(R) moveBack();
moveBack(input)へと転送されます。

back(ElementType!(R) val);
余分な要素を除いた後 input.back へと転送されます。
opIndex(size_t n);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length があるときに限り定義されます。

ElementType!(R) moveAt(size_t n);
moveAt(input, n) へと転送されます。

void opIndexAssign(ElementType!(R) val, size_t n);
input[input.length - n + 1] へと転送されます。R がランダムアクセスレンジで RR.length があるときに限り定義されます。

typeof(this) opSlice(size_t lower, size_t upper);
Stride のスライスは、元のレンジがスライスをサポートしていれば使用可能です。

size_t length();
レンジの長さを返す基本関数です。 input.length に転送されるため、 hasLength!(R) が真のときに限り定義されます。
template Chain(R...) if (allSatisfy!(isInputRange,staticMap!(Unqual,R)))
Chain!(R) chain(R...)(R input);
複数のレンジを順にたどるレンジです。関数 chain は任意の個数のレンジを引数にとり、Chain!(R1, R2,...) オブジェクトを返します。 レンジ自体の型は異なっていても構いませんが、要素型は統一されている必要があります。 結果は front, popFront, empty を提供するレンジになります。 入力が全て length を持つランダムアクセスレンジならば、 Chain その二つの機能も同時に提供します。

レンジが1つだけ Chainchain に渡された場合 Chain 型はそのレンジへのaliasとなります。

Example:
int[] arr1 = [ 1, 2, 3, 4 ];
int[] arr2 = [ 5, 6 ];
int[] arr3 = [ 7 ];
auto s = chain(arr1, arr2, arr3);
assert(s.length == 7);
assert(s[5] == 6);
assert(equal(s, [1, 2, 3, 4, 5, 6, 7][]));

struct Radial(Range) if (isRandomAccessRange!(Unqual!(Range)) && hasLength!(Unqual!(Range)));
Radial!(R) radial(R)(R r);
Radial!(R) radial(R)(R r, size_t startingIndex);
ランダムアクセスレンジを、 指定されたインデックスから始めて左右に広がりながら順にアクセスします。 始点を与えなかった場合、 レンジのちょうど中央から開始します。元のレンジ全体を列挙し終わると終了します。

Example:
int[] a = [ 1, 2, 3, 4, 5 ];
assert(equal(radial(a), [ 3, 4, 2, 5, 1 ][]));
a = [ 1, 2, 3, 4 ];
assert(equal(radial(a), [ 2, 3, 1, 4 ][]));

this(R input);
レンジを受け取って中央からの列挙を開始します。 長さが偶数のレンジの場合は、中心のすぐ左の要素から列挙が始まります。 二番目は、一番目のすぐ右の要素です。 このコンストラクタを簡単に呼び出すには、 補助関数 radial(input) を使用します。
this(R input, size_t startingPoint);
レンジを受け取って input[mid] からの列挙を開始します。 二番目は、 一番目のすぐ右の要素です。input[mid] の右に要素がない場合は、input[mid - 1] から降順に列挙が行われます。このコンストラクタを簡単に呼び出すには、 補助関数 radial(input,startingPoint) を使用します。
Radial opSlice();
this を返します。
bool empty();
全ての要素を列挙し終わっていれば true を返す、 レンジの基本操作です
void popFront();
レンジを一つ次の要素に進める基本操作です

ElementType!(R) moveFront();

front(ElementType!(R) val);

typeof(this) save();

struct Take(Range) if (isInputRange!(Unqual!(Range)) && (!hasSlicing!(Unqual!(Range)) || isNarrowString!(Unqual!(Range))));
R take(R)(R input, size_t n);
Take!(R) take(R)(R input, size_t n);
Take!(R) take(R)(R input, size_t n);
レンジから(遅延評価で)最大 n 個までの要素を取り出します。 特に、無限レンジを扱うときに有用です。 入力が ランダムアクセスレンジで length がサポートされていた場合、Take もそれらの機能を同様にサポートします。

Example:
int[] arr1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
auto s = take(arr1, 5);
assert(s.length == 5);
assert(s[4] == 5);
assert(equal(s, [ 1, 2, 3, 4, 5 ][]));

size_t popFrontN(Range)(ref Range r, size_t n);
レンジ r 自身 (コピーではない) を、nr.popFront を呼び出して先に進めます。rpopFrontN に参照渡しされるので、元々のレンジが影響されます。スライス操作をサポートするレンジならば Ο(1) ステップ、それ以外では Ο(n) ステップの時間がかかります。

Example:
int[] a = [ 1, 2, 3, 4, 5 ];
a.popFrontN(2);
assert(a == [ 3, 4, 5 ]);

size_t popBackN(Range)(ref Range r, size_t n);
レンジ r 自身 (コピーではない) を、nr.popBack を呼び出して終端を縮めます。 rpopBackN に参照渡しされるので、元々のレンジが影響されます。 スライス操作をサポートするレンジならば Ο(1) ステップ、それ以外では Ο(n) ステップの時間がかかります。

Example:
int[] a = [ 1, 2, 3, 4, 5 ];
a.popBackN(2);
assert(a == [ 1, 2, 3 ]);

struct Repeat(T);
Repeat!(T) repeat(T)(T value);
一つの値を永久に繰り返します。例:
enforce(equal(take(repeat(5), 4), [ 5, 5, 5, 5 ][]));

T front();
T back();
bool empty;
void popFront();
void popBack();
Repeat!(T) save();
T opIndex(uint);
レンジプリミティブの実装

Take!(Repeat!(T)) replicate(T)(T value, size_t n);
value をちょうど n 回繰り返します。take(repeat(value), n) と同等です。

struct Cycle(Range) if (isForwardRange!(Unqual!(Range)) && !isInfinite!(Unqual!(Range)));
template Cycle(R) if (isInfinite!(R))
struct Cycle(R) if (isStaticArray!(R));
Cycle!(R) cycle(R)(R input);
Cycle!(R) cycle(R)(R input, size_t index);
Cycle!(R) cycle(R)(R input);
Cycle!(R) cycle(R)(ref R input, size_t index = 0);
指定された前進レンジを無限に繰り返します。 元々のレンジが無限だった場合(Cycle を適用しても結果は変わらないので)、 Cycle はそのことを検出し、元のレンジ型へのaliasとして定義されます。 元のレンジがランダムアクセスならば、Cycle もランダムアクセスになり、初期インデックス index を受け取るコンストラクタを提供します。Cycle は、パフォーマンス上の理由で、静的配列に対しては特殊化した定義が適用されます。

Example:
assert(equal(take(cycle([1, 2][]), 5), [ 1, 2, 1, 2, 1 ][]));

Tip:
このテンプレートは、単純な環状バッファを実装する優れた方法です。

front(ElementType!(R) val);
bool empty;
void popFront();
opIndexAssign(ElementType!(R) val, size_t n);
Cycle!(R) save();
Ditto

struct Zip(Ranges...) if (Ranges.length && allSatisfy!(isInputRange,staticMap!(Unqual,Ranges)));
Zip!(R) zip(R...)(R ranges);
Zip!(R) zip(R...)(StoppingPolicy sp, R ranges);
複数のレンジを並行してたどります。 Zipレンジの要素型はプロキシとなっているタプルで、n番目のレンジに対応する値は e[n] で取得できます。

Example:
int[] a = [ 1, 2, 3 ];
string[] b = [ "a", "b", "c" ];
// prints 1:a 2:b 3:c
foreach (e; zip(a, b))
{
    write(e[0], ':', e[1], ' ');
}
Zip は、渡されたレンジの最大公約数的な機能を提供します。 たとえば、全てのレンジがランダムアクセス可能ならランダムアクセス可能になりますし、 書き換えやswapが可能ならZipレンジでもそれは可能です。この機能によって、Zip は複数レンジを同時に操作できる非常に強力な機能となります。 たとえば、 以下のコードは2つの配列を並列してソートします。

int[] a = [ 1, 2, 3 ];
string[] b = [ "a", "b", "c" ];
sort!("a[0] > b[0]")(zip(a, b));
assert(a == [ 3, 2, 1 ]);
assert(b == [ "c", "b", "a" ]);

this(R rs, StoppingPolicy s = StoppingPolicy.shortest);
オブジェクトを構築します。通常、 std.range.zip 補助関数から間接的に呼び出されます。
bool empty;
レンジが終端に来ていれば true を返します。 終端の定義はStoppingPolicy依存です。
ElementType front();
現在の先頭要素へのプロキシを返します。
void front(ElementType v);
全てのレンジへ front を設定します。

ElementType moveFront();
Frontを除きます

ElementType back();
現在の末尾要素へのプロキシを返します。
ElementType moveBack();
末尾を除いて返します。

void back(ElementType v);
現在の末尾要素を設定します。

void popFront();
全てのレンジを popFront で進めます。
void popBack();
全てのレンジを popBack で縮めます。
size_t length();
このレンジの length を返します。全ての内蔵レンジが length を定義しているときのみ定義されます。
Zip opSlice(size_t from, size_t to);
スライスを返します。 全ての内蔵レンジがスライスを計算できる場合にのみ定義されます。
ElementType opIndex(size_t n);
複合レンジの第 n 要素を返します。 全てのレンジがランダムアクセスな場合に定義されます。

void opIndexAssign(ElementType v, size_t n);
複合レンジの第 n 要素へ代入します。 全てのレンジがランダムアクセスな場合に定義されます。

ElementType moveAt(size_t n);
破壊的に複合レンジの第 n 要素を読み取ります。 全てのレンジがランダムアクセスな場合に定義されます。

enum StoppingPolicy;
Zip の終了条件を定義します。 デフォルトでは、一番短いレンジの長さに合わせます。
shortest
一番短いレンジが終わったタイミングで終了
longest
一番長いレンジが終わったタイミングで終了
requireSameLength
全てのレンジが同じ長さであることを要求
struct Lockstep(Ranges...) if (Ranges.length > 1 && allSatisfy!(isInputRange,staticMap!(Unqual,Ranges)));
複数のレンジを並行して foreach ループで回るための補助型です。 一つしかレンジが渡されなければ、Lockstep はその引数へのaliasになります。 違う長さのレンジが渡され s == StoppingPolicy.shortest ならば、一番短いレンジに合わせます。 違う長さのレンジが渡され s == StoppingPolicy.requireSameLength ならば、 例外が飛びます。sStoppingPolicy.longest は指定できず、 指定すると例外が飛びます。

BUGS:
左辺値アクセスできないレンジで refforeach に使うと、コンパイルは通ってしまいますが、 意図した書き換えなどは行えません。

Examples:
auto arr1 = [1,2,3,4,5];
auto arr2 = [6,7,8,9,10];

foreach(ref a, ref b; lockstep(arr1, arr2))
{
   a += b;
}

assert(arr1 == [7,9,11,13,15]);

// Lockstep ではインデックスによるアクセスも可能です:
foreach(index, a, b; lockstep(arr1, arr2)) {
    writefln("Index %s:  a = %s, b = %s", index, a, b);
}

struct Recurrence(alias fun,StateType,size_t stateSize);
Recurrence!(fun,CommonType!(State),State.length) recurrence(alias fun, State...)(State initial);
初期値と、前の値から次の値を計算する漸化式を与えて、 数列を生成します。 結果は無限の前進レンジとなります。 Recurrence 型を直接宣言することは稀で、 多くの場合は、補助関数 recurrence を使ってレンジを作成します。

recurrence を呼び出すと、テンプレート引数で指定された式を使って、 通常の引数で指定された初期値から次の値を計算します。 例えば、 フィボナッチ数列の場合、 直前の2つの値を使って次のフィボナッチ数を計算する必要があるため、 初期値は2つとなります(従ってサイズ2のステートを持ちます)。

文字列形式で関数を渡す場合、状態は "a" という名前を持ち、数列の何番目の要素であるかを表す "n" という名前のゼロベースのインデックスを持ちます。 文字列では、a[n] の値を a[n - 1], a[n - 2], a[n - 3],..., a[n - stateSize] から計算する式を書きます。 ステート数は、 recurrence に渡された実引数の個数で決まります。 ステート数やその管理は適切にRecurrenceの内部で行われます。

Example:
// a[0] = 1, a[1] = 1, 以下 a[n+1] = a[n-1] + a[n] で計算
auto fib = recurrence!("a[n-1] + a[n-2]")(1, 1);
// 最初の10個のフィボナッチ数を表示
foreach (e; take(fib, 10)) { writeln(e); }
// 最初の10個の階乗数を表示
foreach (e; take(recurrence!("a[n-1] * n")(1), 10)) { writeln(e); }

struct Sequence(alias fun,State);
Sequence!(fun,Tuple!(State)) sequence(alias fun, State...)(State args);
SequenceRecurrence eと似ていますが、 数式が closed form であることが違う点です。これはつまり、数列のn番目の値は 初期値と n そのものから直接計算できるという意味です。 結果として、Sequence はランダムアクセスレンジとなり、通常の Recurrence が前進レンジにしかならないのと対照的です。

ステートは Tuple で保持されるため、 違う型の要素を持たせることも可能です。

Example:
// a[0] = 1, a[1] = 2, a[n] = a[0] + n * a[1]
auto odds = sequence!("a[0] + n * a[1]")(1, 2);

Iota!(CommonType!(Unqual!(B),Unqual!(E)),S) iota(B, E, S)(B begin, E end, S step);
Iota!(CommonType!(Unqual!(B),Unqual!(E)),uint) iota(B, E)(B begin, E end);
Iota!(Unqual!(E),uint) iota(E)(E end);
struct Iota(N,S) if ((isIntegral!(N) || isPointer!(N)) && isIntegral!(S));
struct Iota(N,S) if (isFloatingPoint!(N) && isNumeric!(S));
begin, begin + step, begin + 2 * step, ..., と進めて end まで(ただしendは含まない)の部分列をレンジとして取り出します。結果はランダムアクセスレンジになります。 2引数バージョンは step = 1 の扱いになります。

Example:
auto r = iota(0, 10, 1);
assert(equal(r, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][]));
r = iota(0, 11, 3);
assert(equal(r, [0, 3, 6, 9][]));
assert(r[2] == 6);
auto rf = iota(0.0, 0.5, 0.1);
assert(approxEqual(rf, [0.0, 0.1, 0.2, 0.3, 0.4]));

enum TransverseOptions;
FrontTransversalTransversal (下参照) に対するオプション

assumeJagged
レンジ内の各レンジは異なる長さであると仮定されます。 (例: jagged array)
enforceNotJagged
レンジ内の全てのレンジは同じ長さであることが強制されます。 (例: 長さが一定の二次元配列) チェックは構築時に最初に一度だけ行われます。

assumeNotJagged
チェックなしで、レンジ内の全てのレンジは同じ長さであることを仮定します。 このオプションは、 既に長さが一定であることをチェック済みのレンジに適用するときなどに有用です。

struct FrontTransversal(Ror,TransverseOptions opt = TransverseOptions.assumeJagged);
FrontTransversal!(RangeOfRanges,opt) frontTransversal(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRanges rr);
レンジのレンジを受け取り、 それぞれの先頭要素を順に列挙します。

Example:
int[][] x = new int[][2];
x[0] = [1, 2];
x[1] = [3, 4];
auto ror = frontTransversal(x);
assert(equal(ror, [ 1, 3 ][]));

this(RangeOfRanges input);
入力からの構築
bool empty;
ElementType moveFront();
void popFront();
typeof(this) save();
void popBack();
ElementType moveBack();
ElementType moveAt(size_t n);
void opIndexAssign(ElementType val, size_t n);
前進レンジの基本操作
typeof(this) opSlice(size_t lower, size_t upper);
RangeOfRanges がスライシング可能で、 インデックスアクセス可能な条件が全て満たされていれば、全体としてスライシング可能です。
struct Transversal(Ror,TransverseOptions opt = TransverseOptions.assumeJagged);
Transversal!(RangeOfRanges,opt) transversal(TransverseOptions opt = TransverseOptions.assumeJagged, RangeOfRanges)(RangeOfRanges rr, size_t n);
レンジのレンジを受け取り、それぞれの第 n 要素を順に列挙します。 ランダムアクセスレンジのレンジを渡す必要があります。

Example:
int[][] x = new int[][2];
x[0] = [1, 2];
x[1] = [3, 4];
auto ror = transversal(x, 1);
assert(equal(ror, [ 2, 4 ][]));

this(RangeOfRanges input, size_t n);
入力とインデックスから構築
bool empty;
E moveFront();
front(E val);
void popFront();
typeof(this) save();
void popBack();
E moveBack();
back(E val);
E moveAt(size_t n);
void opIndexAssign(E val, size_t n);
前進レンジの基本操作
typeof(this) opSlice(size_t lower, size_t upper);
RangeOfRanges がスライシング可能で、 インデックスアクセス可能な条件が全て満たされていれば、全体としてスライシング可能です。
ElementType!(R) moveFront(R)(R r);
r のfrontをムーブし返します。r.front はどんなリソースも保持していない破棄可能な状態になります (通常、 .init 値と等しくなります)

ElementType!(R) moveBack(R)(R r);
r のbackをムーブし返します。r.front はどんなリソースも保持していない破棄可能な状態になります (通常、 .init 値と等しくなります)

ElementType!(R) moveAt(R)(R r, size_t i);
r の第i要素をムーブし返します。r.front はどんなリソースも保持していない破棄可能な状態になります (通常、 .init 値と等しくなります)

interface InputRange(E);
このインターフェイスは、要素型 E の入力レンジに対する仮想関数ベースのアクセスを提供することを目的としています。 これは、DLL関数や、汎用のレンジを受け取りたい仮想関数など、 定まったバイナリインターフェイスが必要な場合に役立ちます。 注意点として、 isInputRange やその他テンプレートは、構造的なインターフェイス適合を検査するもので、 この特定のインターフェイス型をimplementしていることを検査する物ではありません。

Examples:
 class UsesRanges {
     void useRange(InputRange range) {
         // Function body.
     }
 }

 // 新しいレンジ型
 auto squares = map!"a * a"(iota(10));

 // interface でラップ
 auto squaresWrapped = inputRangeObject(squares);

 // 使う
 auto usesRanges = new UsesRanges;
 usesRanges.useRange(squaresWrapped);

Limitations:
これらのインターフェイスは要素への ref アクセスは転送できません。

また、ラップしたレンジの無限性は伝搬されません。

ランダムアクセスレンジでない場合、length も伝搬されません。

E front();

E moveFront();

void popFront();

bool empty();

int opApply(int delegate(ref E));
int opApply(int delegate(ref size_t, ref E));
foreach ループでは opApply が使われます。 1繰り返しにつき1回のdelegateの呼び出しの方が、3回の仮想関数呼び出しより速いためです。

BUGS:
ref 変数がループ変数として使われていても、 ループ変数への変更は元データに伝搬されません。 また、ループ変数のアドレスが外にエスケープすると、 未定義動作となります。これは DMD bug 2443 に関連しています。

interface ForwardRange(E): InputRange!(E);
前進レンジ型 E のインターフェイスです

ForwardRange!(E) save();

interface BidirectionalRange(E): ForwardRange!(E);
双方向レンジ型 E のインターフェイスです

BidirectionalRange!(E) save();

E back();

E moveBack();

void popBack();

interface RandomAccessFinite(E): BidirectionalRange!(E);
有限のランダムアクセスレンジ型 E のインターフェイスです

RandomAccessFinite!(E) save();

E opIndex(size_t);

E moveAt(size_t);

size_t length();

RandomAccessFinite!(E) opSlice(size_t, size_t);

interface RandomAccessInfinite(E): ForwardRange!(E);
無限のランダムアクセスレンジ型 E のインターフェイスです

E moveAt(size_t);

RandomAccessInfinite!(E) save();

E opIndex(size_t);

interface InputAssignable(E): InputRange!(E);
InputRange を代入可能にします。

void front(E newVal);

interface ForwardAssignable(E): InputAssignable!(E), ForwardRange!(E);
ForwardRange を代入可能にします。

ForwardAssignable!(E) save();

interface BidirectionalAssignable(E): ForwardAssignable!(E), BidirectionalRange!(E);
BidirectionalRange を代入可能にします。

BidirectionalAssignable!(E) save();

void back(E newVal);

interface RandomFiniteAssignable(E): RandomAccessFinite!(E), BidirectionalAssignable!(E);
RandomAccessFinite を代入可能にします。

RandomFiniteAssignable!(E) save();

void opIndexAssign(E val, size_t index);

interface OutputRange(E);
出力レンジ型 E のインターフェイスです。使い方は InputRange などなどと同様です。

void put(E);

class OutputRangeObject(R,E...): staticMap!(OutputRange,E);
OutputRange インターフェイスを全ての型Eに対して実装し、 put メソッドをそれぞれの E について仮想関数としてラップして提供します。

template MostDerivedInputRange(R) if (isInputRange!(Unqual!(R)))
R にもっともよくマッチするインターフェイス型を返します。

template InputRangeObject(R) if (isInputRange!(Unqual!(R)))
R に最もよくマッチするインターフェイス型を実装し、 関連するレンジプリミティブを全て仮想関数でラップし提供します。R が既に InputRange インターフェイスを継承していれば、単なるaliasとなります。

InputRangeObject!(R) inputRangeObject(R)(R range);
InputRangeObject を作る便利関数です。

template outputRangeObject(E...)
OutputRangeObject をレンジ型 R と受理する要素型のリスト E から作る便利関数です。

Examples:
uint[] outputArray;
auto app = appender(&outputArray);
auto appWrapped = outputRangeObject!(uint, uint[])(app);
static assert(is(typeof(appWrapped) : OutputRange!(uint[])));
static assert(is(typeof(appWrapped) : OutputRange!(uint)));

template outputRangeObject(R)

OutputRangeObject!(R,E) outputRangeObject(R range);

struct SortedRange(Range,alias pred = "a < b") if (isRandomAccessRange!(Unqual!(Range)));
ソート済みのランダムアクセスレンジを表します。 通常のレンジプリミティブに加え、二分探索による高速な検索が実装されています。 SortedRange をソートしていないレンジ r から作るには、std.algorithm.sort を使用し r を破壊的に並び替えて対応する SortedRange を作ります。既にソート済みとわかっているレンジ r から SortedRange を作るには、assumeSorted を以下のように使用します。

Example:
auto a = [ 1, 2, 3, 42, 52, 64 ];
auto r = assumeSorted(a);
assert(r.canFind(3));
assert(!r.canFind(32));
auto r1 = sort!"a > b"(a);
assert(r1.canFind(3));
assert(!r1.canFind(32));
assert(r1.release() == [ 64, 52, 42, 3, 2, 1 ]);
SortedRange はランダムアクセスより弱いレンジを受け取ることもできますが、 それらに対しては意味のある機能を提供できません。したがって、 SortedRange は今のところランダムアクセスレンジに限定されています。

元のレンジのコピーが作られることはありません。 ソート済みという仮定が壊される形で SortedRange の裏で元のレンジが変更された場合 SortedRange は間違った動作をします。

Example:
auto a = [ 1, 2, 3, 42, 52, 64 ];
auto r = assumeSorted(a);
assert(r.canFind(42));
swap(a[2], a[5]); // 元のレンジをソート済みでなくするのは不正
assert(!r.canFind(42)); // 通るべきでないが通ってしまう

bool empty();
typeof(this) save();
ElementType!(R) front();
void popFront();
ElementType!(R) back();
void popBack();
ElementType!(R) opIndex(size_t i);
typeof(this) opSlice(size_t a, size_t b);
size_t length();
レンジプリミティブ.

R release();
コントロールしているレンジを解放し返します。

typeof(this) lowerBound(V)(V value)
この関数は、レンジ r が左右に分割でき、左側 r1 の要素 e1pred(e1, value)true になり、 右側 r2 の要素 e2pred(e2, value)false になる、と仮定して実行されます。この仮定の下で、lowerBound は二分探索によって r1、つまり pred が常に true となる左レンジを見つけだします。Ο(log(r.length))pred を呼び出します。 この計算量を上回ってしまうため、前提条件はチェックされません。 value の型と ElementType!(Range) とが違っていても、 pred 適用できれば問題ありません。参照: STL の lower_bound

Precondition:
find!(not!(pred))(r, value).length + find!(pred)(retro(r), value).length == r.length

Example:
   auto a = assumeSorted([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]);
   auto p = a.lowerBound(4);
   assert(p.release == [ 0, 1, 2, 3 ]);

typeof(this) upperBound(V)(V value)
この関数は、レンジ r が左右に分割でき、左側 r1 の要素 e1pred(value, e1)false になり、 右側 r2 の要素 e2pred(value, e2)true になる、と仮定して実行されます。 (lowerBound の定義との違いに注意して下さい。 pred の引数順とtrue/falseが逆転しています) この仮定の下で、lowerBound は二分探索によって r2、つまり pred が常に true となる左レンジを見つけだします。Ο(log(r.length))pred を呼び出します。 この計算量を上回ってしまうため、前提条件はチェックされません。value の型と ElementType!(Range) とが違っていても、 pred 適用できれば問題ありません。参照: STL の upper_bound

Precondition:
find!(pred)(r, value).length + find!(not!(pred))(retro(r), value).length == r.length

Example:
   auto a = assumeSorted([ 1, 2, 3, 3, 3, 4, 4, 5, 6 ]);
   auto p = a.upperBound(3);
   assert(p == [4, 4, 5, 6]);

typeof(this) equalRange(V)(V value)
レンジが lowerBound!(pred)(r, value)upperBound!(pred)(r, value) の両方を満たしているという仮定の下で、 equalRange!(pred)(r, v) を呼び出すと、 pred(e, value)==truepred(value, e)==false を同時に満たす全ての要素 e を含むレンジを返します。Ο(log(r.length))pred を呼び出します。参照: STL の equal_range

Precondition:
find!(not!(pred))(r, value).length + find!(pred)(retro(r), value).length == r.length && find!(pred)(r, value).length + find!(not!(pred))(retro(r), value).length == r.length

Example:
   auto a = [ 1, 2, 3, 3, 3, 4, 4, 5, 6 ];
   auto r = equalRange(a, 3);
   assert(r == [ 3, 3, 3 ]);

bool canFind(V)(V value);
ソート済みと仮定されるレンジ range の中に value があれば true を返します。Ο(log(r.length))less を呼び出します。参照: STL の binary_search