3.1. はじめの一歩

まず最初に、Bezelが提供するコンテナのうち、標準コンテナと同名のvectorlistmapの基本的な扱い方を示す。

Bezelのvectorは、動的配列を表す列コンテナである。使い方は標準コンテナのvectorとおおむね同一と考えてよい: 例えば次のようにして使用する。

例 3.1. vectorの使い方 (1)

#include <iostream>
#include <ostream>
#include <bezel/vector.h>

int main()
{
  typedef bezel::vector::vector<int> C;
  typedef C::iterator IT;

  C v;

  v.push_back(1);
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  for (IT p = v.begin(); p != v.end(); ++p) {
    std::cout << *p << std::endl;
  }

  return 0;
}

この例では、int型の要素のための動的配列vに値1123を格納し、格納されたすべての値を先頭から順に標準出力へと出力している。動的配列にBezelのコンテナbezel::vector::vectorを用いている。末尾へと要素を追加するpush_back、列の先頭要素または終端要素の次の要素を指す反復子を得るbeginおよびend、反復子の型名iteratorなどの扱い方は、すべて標準コンテナのstd::vectorと同一である。また、vから得られる反復子はSTLのランダムアクセス反復子の条件を満たしているので、vをSTLの汎用アルゴリズムなどと組み合わせて用いることができる点でもstd::vectorと変わらない。

一方、bezel::vector::vectorの2番目以降のテンプレートパラメータは、std::vectorのようにSTLのアロケータを指定するためのものではなく、コンテナの振る舞いを制御するポリシークラスを指定するためのものである。例えば記憶領域の割り当てにstd::mallocを用いるように変更するなら、次のようにすればよい。

例 3.2. vectorの使い方 (2)

#include <iostream>
#include <ostream>
#include <bezel/array_allocation_policy/std_malloc.h>
#include <bezel/vector.h>

int main()
{
  typedef bezel::vector::vector<
    int,
    bezel::vector::allocation_is<
      bezel::array_allocation_policy::std_malloc<> >
  > C;
  typedef C::iterator IT;

  C v;

  v.push_back(1);
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  for (IT p = v.begin(); p != v.end(); ++p) {
    std::cout << *p << std::endl;
  }

  return 0;
}

この例では、記憶領域の割り当てにstd::mallocを用いるよう指示するために、bezel::vector::vectorに対してbezel::array_allocation_policy::std_mallocを与えている。bezel::array_allocation_policy::std_mallocは、std::mallocを用いて記憶領域の割り当てを行うポリシークラスである。また、このポリシークラスのためのヘッダファイルの読み込みを追加している。この変更により、vstd::mallocを用いて記憶領域を割り当てるようになる。

bezel::vector::allocation_isは、2番目以降のテンプレートパラメータを順不同に与えるためのbezel::vector::vector用の緩衝材である(詳細は項5.6. 「名前付きテンプレートパラメータ」を参照のこと)。複数のポリシークラスを指定する際にその順序を気にする必要はない: 例えば次の通り。

例 3.3. vectorの使い方 (3)

#include <iostream>
#include <ostream>
#include <bezel/array_allocation_policy/std_malloc.h>
#include <bezel/vector.h>
#include <bezel/vector/capacity_growth_policy/half_again.h>

int main()
{
  typedef bezel::vector::vector<
    int,
    bezel::vector::allocation_is<
      bezel::array_allocation_policy::std_malloc<> >,
    bezel::vector::capacity_growth_is<
      bezel::vector::capacity_growth_policy::half_again>
  > C;

  ...
}

この例ではbezel::vector::vectorに対して2つのポリシークラスを指定しているが、bezel::vector::allocation_is<bezel::array_allocation_policy::std_malloc<> >bezel::vector::capacity_growth_is<bezel::vector::capacity_growth_policy::half_again>はどちらを先に記述しても構わない。

長いクラス名を記述するのが面倒であれば、適宜usingを用いて記述を短縮するとよい。例えば次の通り。

例 3.4. vectorの使い方 (4)

int main()
{
  using namespace bezel::vector;
  using namespace bezel::array_allocation_policy;

  typedef vector<
    int,
    allocation_is<std_malloc<> >,
    capacity_growth_is<capacity_growth_policy::half_again>
  > C;

  ...
}

このようにBezelのコンテナは、テンプレートパラメータにポリシークラスを指定することで、記憶領域の割り当て方法、アルゴリズムとデータ構造、デバッグ向けチェック機構の有無などといった振る舞いを外部から変更できる。

Bezelのlist(bezel::list::list)は、連結リストによる列コンテナである。listvectorと同様に、ポリシークラスを与えない場合の扱い方は標準コンテナのlistとほぼ同一である。例えば次の通り。

例 3.5. listの使い方 (1)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>
#include <bezel/list.h>

int main()
{
  typedef std::string T;
  typedef bezel::list::list<T> C;

  C v;

  {
    T s;
    while (getline(std::cin, s)) v.push_back(s);
  }
  v.sort();
  std::copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, "\n"));

  return 0;
}

listへのポリシークラスの与え方はvectorと同様である。例えば次の通り。

例 3.6. listの使い方 (2)

#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>
#include <bezel/list.h>
#include <bezel/list/data_structure_policy/singly_linked.h>

int main()
{
  typedef std::string T;
  typedef bezel::list::list<
    T,
    bezel::list::data_structure_is<
      bezel::list::data_structure_policy::singly_linked>,
  > C;

  ...
}

Bezelのmap(bezel::map::map)は、2分探索木による連想配列である。mapもまた、標準コンテナとほぼ同一のインタフェースを持つ。例えば次のようにして用いる。

例 3.7. mapの使い方 (1)

#include <iostream>
#include <ostream>
#include <string>
#include <bezel/map.h>

int main()
{
  typedef std::string K;
  typedef std::size_t V;
  typedef bezel::map::map<K, V> C;
  typedef C::iterator IT;

  C v;

  {
    K s;
    while (std::cin >> s) ++v[s];
  }

  for (IT p = v.begin(); p != v.end(); ++p) {
    std::cout << p->first << ' ' << p->second << std::endl;
  }

  return 0;
}

vectorlistとは異なり、mapbinary_search_treeに対するコンテナアダプタとして実装されている。そのため、ポリシークラスを与えるときは次のように記述する必要がある。

例 3.8. mapの使い方 (2)

#include <functional>
#include <iostream>
#include <ostream>
#include <string>
#include <bezel/binary_search_tree.h>
#include <bezel/map.h>
#include <bezel/scalar_allocation_policy/std_malloc.h>

int main()
{
  typedef std::string K;
  typedef std::size_t V;
  typedef bezel::map::map<
    K, V, std::less<K>,
    bezel::binary_search_tree::basic_binary_search_tree<
      bezel::binary_search_tree::allocation_is<
        bezel::scalar_allocation_policy::std_malloc<> > >
  > C;
  ...
}