英語版
このページの英語版を見る

std.container

このモジュールは汎用コンテナを定義する。

構築 さまざまなコンテナを実装するために、構造体ベースとクラスベースの両方のアプローチが使用されている。 std.container.util.makeどちらのアプローチでも 均一な構造を構築できる。

import std.container;
// 値1、2、3の両方を含むred-black treeと配列を構築する。
// RedBlackTreeは通常、`new`を使って割り当てるべきである
RedBlackTree!int rbTree = new RedBlackTree!int(1, 2, 3);
// しかし、`new`はArrayと一緒に使用すべきではない
Array!int array = Array!int(1, 2, 3);
// `make`は差異を隠蔽する
RedBlackTree!int rbTree2 = make!(RedBlackTree!int)(1, 2, 3);
Array!int array2 = make!(Array!int)(1, 2, 3);
make は、与えられた引数から要素型を推論できることに注意。
"note""注釈:"
import std.container;
auto rbTree = make!RedBlackTree(1, 2, 3); // RedBlackTree!int
auto array = make!Array("1", "2", "3"); // Array!string
参照セマンティクス すべてのコンテナは参照セマンティクスを持ち、これは、 代入後、両方の変数が同じ基礎データを参照することを意味する。 xml-ph-0000@deepl.internal コンテナのコピーを作成するには、

参照セマンティクス すべてのコンテナは参照セマンティクスを持ち、これは、 代入後、両方の変数が同じ基礎となるデータを参照することを意味する。

コンテナのコピーを作成するには、c.dup コンテナプリミティブを使用する。
import std.container, std.range;
Array!int originalArray = make!(Array!int)(1, 2, 3);
Array!int secondArray = originalArray;
assert(equal(originalArray[], secondArray[]));

// 一方を変更すると、もう一方も変更される!
originalArray[0] = 12;
assert(secondArray[0] == 12);

// secondArrayは、originalArrayの独立したコピーを参照するようになった
secondArray = originalArray.dup;
secondArray[0] = 1;
// originalArrayが影響を受けていないことを示すassert
assert(originalArray[0] == 12);
Attention: コンテナがクラスとして実装されている場合、 初期化されていないインスタンスを使用すると、nullポインタの参照が発生する可能性がある。
import std.container;

RedBlackTree!int rbTree;
rbTree.insert(5); // ヌルポインタの非参照
未初期化の構造体ベースのコンテナを使用しても動作するが、これは、構造体が 使用時に自動的に初期化されるためである。しかし、この時点ではコンテナには 同一性がなく、代入によって同じデータへの参照が2つ作成されることはない。
import std.container;

// 初期化されていない配列を作成する
Array!int array1;
// array2はarray1を指していない
Array!int array2 = array1;
array2.insertBack(42);
// したがって、array1は影響をうけない
assert(array1.empty);

// 初期化後は、参照のセマンティクスは期待通りに動作する
array1 = array2;
// array2にも同様に影響するようになった
array1.removeBack();
assert(array2.empty);
したがって、コンテナは常にstd.container.util.make
実際、コンテナを別のコンテナに入れるためには、これは必要である。 例えば、10個の空のArrayArray を構築するには、make を10回呼び出す以下のものを使用する。
"example""例"
import std.container, std.range;

auto arrOfArrs = make!Array(generate!(() => make!(Array!int)).take(10));
サブモジュール このモジュールは以下のサブモジュールで構成される。 xml-ph-0000@deepl.internal

サブモジュール このモジュールは以下のサブモジュールで構成される。

  • このモジュールは、 std.container.arrayモジュールは、 メモリを決定論的に制御する配列型を提供し、 組み込み配列とは異なり、GCに依存しない。
  • この std.container.binaryheapモジュールは、 ユーザーが提供するランダムアクセス可能な範囲に適用できるバイナリヒープの実装を提供する。
  • この std.container.dlistモジュールは 双方向リンクリストの実装を提供する。
  • この std.container.rbtreeモジュールは、 赤黒木を実装する。
  • この std.container.slistモジュールは 単方向リンクリストを実装する。
  • この std.container.utilモジュールには、 コンテナ実装で一般的に使用されるいくつかの汎用ツールが含まれている。

コンテナのプライマリレンジ 一部のコンテナでは、例えばopIndexc.frontc.back などを介して、要素に直接アクセスできるが、 コンテナの内容へのアクセスや変更は、通常は プライマリレンジ型を介して行われる。 これは、C.Range というエイリアスである。例えば、Array!int のプライマリレンジ型は、Array!int.Range である。

コンテナのメンバ関数のドキュメントでRange 型のパラメータが使用されている場合、これは、このコンテナのプライマリレンジ型を参照している 多くの場合、Take!Range が使用され、その場合、 範囲はコンテナ内の要素の範囲を指す。これらのパラメータへの引数must は、処理対象のコンテナインスタンスと同じものから取得される。 多くの汎用範囲アルゴリズムが 入力範囲と同じ範囲型を返すことに注意することが重要である。
import std.algorithm.comparison : equal;
import std.algorithm.iteration : find;
import std.container;
import std.range : take;

auto array = make!Array(1, 2, 3);

// `find`は要素"2"まで進んだArray!int.Rangeを返す
array.linearRemove(array[].find(2));

assert(array[].equal([1]));

array = make!Array(1, 2, 3);

// `linearRemove`に与えられた範囲は、
// 要素"2"のみにまたがるTake!(Array!int.Range)である
array.linearRemove(array[].find(2).take(1));

assert(array[].equal([1, 3]));
任意の範囲がメンバ関数の引数として渡される場合、 ドキュメントでは通常、パラメータのテンプレート化された型をStuff と参照する。
"function関数
import std.algorithm.comparison : equal;
import std.container;
import std.range : iota;

auto array = make!Array(1, 2);

// `iota`によって返される範囲型はArrayとは全く関係がないが、
// Array.insertBackでは問題ない:
array.insertBack(iota(3, 10));

assert(array[].equal([1, 2, 3, 4, 5, 6, 7, 8, 9]));
コンテナのプリミティブ コンテナはクラス階層を形成せず、その代わりに 共通のプリミティブセットを実装する(下記の表を参照)。これらのプリミティブはそれぞれ 特定の最悪ケースの複雑性を保証し、汎用コードの記述を可能にする

コンテナのプリミティブ コンテナはクラス階層を形成せず、その代わりに 共通のプリミティブセットを実装する(下記の表を参照)。これらのプリミティブはそれぞれ、 特定の最悪ケースの複雑性を保証し、コンテナの実装とは独立して汎用コードを記述することを可能にする。

例えば、プリミティブのc.remove(r)c.linearRemove(r) は、r の範囲の要素のシーケンスをコンテナc から削除する。 プリミティブのc.remove(r) は、 最悪の場合でもΟ(nr log nc)の複雑性を保証し、c.linearRemove(r) は、この保証をΟ(nc)に緩和する。
要素のシーケンスは、二重リンクリストから定数時間で削除できるため、DList は、 プリミティブのc.remove(r)だけでなく、c.linearRemove(r) も提供する。一方、 Arrayはc.linearRemove(r) のみを提供する。
以下の表は、コンテナが実装する共通のプリミティブのセットについて説明している。 コンテナはすべてのプリミティブを実装する必要はないが、 プリミティブを実装する場合は、syntax 列に記述された構文をdescription 列に記述されたセマンティクスでサポートしなければならず、 また、big-O記法で表記された最悪の複雑性よりも悪いものであってはならない 。以下、C はコンテナ型、c は コンテナ型の値、·nx値の有効長を表し、x は、単一要素(この場合、 nx1 )、コンテナ、または範囲を表す。
コンテナのプリミティブ
構文 Ο(·) 説明
C(x) nx 別のコンテナまたは範囲から、"C "型のコンテナを作成する。 xが空であっても、作成されるコンテナはnull参照であってはならない。
c.dup nc コンテナの複製を返す。
c ~ x nc + nx cr の結合を返す。x は単一の要素または入力範囲である可能性がある。
x ~ c nc + nx xc の結合を返す。x は、 単一要素または入力範囲型である可能性がある。
反復
c.Range コンテナに関連付けられた主要な範囲型。
c[] log nc コンテナ全体を反復する範囲を返す。 コンテナで定義された順序で。
c[a .. b] log nc キーa からキーb までのコンテナの一部を取得する。
    容量
c.empty 1 コンテナに要素がない場合はtrue を、それ以外はfalse を返す。
c.length log nc コンテナ内の要素数を返す。
c.length = n nc + n コンテナ内の要素数をn に強制する。 コンテナが最終的に大きくなった場合、追加された要素は コンテナに依存した方法で初期化される(通常はT.init )。
c.capacity log nc 再割り当てを発生させることなくコンテナに格納できる要素の最大数を返す。
c.reserve(x) nc capacity を減らすことなく、少なくともx に強制する。
アクセス
c.front log nc コンテナの最初の要素を、コンテナで定義された順序で返す。
c.moveFront log nc 破壊的に読み取り、コンテナの最初の要素を返す。 スロットはコンテナから削除されず、T.init で初期化されたまま残される。 frontref を返す場合は、このルーチンを定義する必要はない。
c.front = v log nc v をコンテナの最初の要素に割り当てる。
c.back log nc コンテナの最後の要素を、コンテナで定義された順序で返す。
c.moveBack log nc 破壊的に読み取り、コンテナの最後の要素を返す。 スロットはコンテナから削除されず、T.init で初期化されたまま残される。 frontref を返す場合は、このルーチンを定義する必要はない。
c.back = v log nc v をコンテナの最後の要素に割り当てる。
c[x] log nc コンテナへのインデックス付きアクセスを提供する。インデックス型は コンテナ定義である。コンテナは複数のインデックス型を定義できる(その結果、 インデックスが重複する可能性もある)。
c.moveAt(x) log nc x の位置にある値を破壊的に読み取り、返す。スロットは コンテナから削除されず、 T.init で初期化されたまま残される。
c[x] = v log nc 指定したインデックスの要素をコンテナに設定する。
c[x] op= v log nc コンテナの指定したインデックスで読み取り・修正・書き込み操作を実行する 。
    操作
e in c log nc e がc に存在する場合、ゼロ以外の値を返す。
c.lowerBound(v) log nc v より小さいすべての要素の範囲を返す。
c.upperBound(v) log nc v より厳密に大きいすべての要素の範囲を返す。
c.equalRange(v) log nc c の要素のうち、v と等しい要素のすべてを返す。
修飾子
c ~= x nc + nx cx を追加する。x は単一の要素または入力範囲型である。
c.clear() nc c 内のすべての要素を削除する。
c.insert(x) nx * log nc c で選択した位置(または複数の位置)に、xc に挿入する。
c.stableInsert(x) nx * log nc c.insert(x) と同じだが、範囲が無効にならないことが保証されている。
c.linearInsert(v) nc c.insert(v) と同じだが、複雑性を線形に緩和する。
c.stableLinearInsert(v) nc c.stableInsert(v) と同じだが、複雑さを線形に緩和する。
c.removeAny() log nc c からいくつかの要素を削除して返す。
c.stableRemoveAny() log nc c.removeAny() と同じだが、イテレータが無効にならないことが保証されている。
c.insertFront(v) log nc vc の先頭に挿入する。
c.stableInsertFront(v) log nc c.insertFront(v) と同じだが、範囲が無効にならないことを保証する。
c.insertBack(v) log nc c の後にv を挿入する。
c.stableInsertBack(v) log nc c.insertBack(v) と同じだが、範囲が無効にならないことを保証する。
c.removeFront() log nc c の先頭の要素を削除する。
c.stableRemoveFront() log nc c.removeFront() と同じだが、範囲が無効にならないことを保証する。
c.removeBack() log nc c の末尾の値を削除する。
c.stableRemoveBack() log nc c.removeBack() と同じだが、範囲が無効にならないことを保証する。
c.remove(r) nr * log nc c からレンジr を削除する。
c.stableRemove(r) nr * log nc c.remove(r) と同じだが、イテレータが無効にならないことを保証する 。
c.linearRemove(r) nc c から範囲を削除するr
c.stableLinearRemove(r) nc c.linearRemove(r) と同じだが、イテレータが無効にならないことを保証する 。
c.removeKey(k) log nc c から、キーk を使用して要素を削除する。 キーの型はコンテナによって定義される。

ソース std/container/package.d sourceソース

License:
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at boost.org/LICENSE_1_0.txt).
Authors:
Steven Schveighoffer, Andrei Alexandrescu