Boost C++ライブラリ

Boost （ブースト）とは、C++の開発者のコミュニティ、およびそのコミュニティによって公開されているオープンソースのソフトウェアライブラリのことを指す。

 概要 
コミュニティとしてのBoostはC++標準化委員会の委員により設立されており、現在でもその多くが構成員として留まっている。このような経緯もあり、BoostコミュニティはC++の標準化において大きな影響力を有している。実際に標準化委員会が発表した「TR1」の2/3以上がBoostライブラリを基にしている。Random, Regex, ThreadなどはいずれもC++11規格の標準ライブラリとして正式に導入・標準化されている。その後もOptionalやAnyなどがC++17規格で導入されており、影響を与え続けている。このことから、Boostは考案された新機能を標準化させる前の試験運用の場であるとも言える。

Boostで公開されるライブラリはコミュニティの公開レビューによって精選されている。Boostを使用して作成したプログラムは、商用、非商用を問わず無償のBoost Software Licenseの下でライセンスされる。

Boostはテンプレートなどを活用して積極的にメタプログラミングやジェネリックプログラミングの技法を取り入れて行く傾向がある。そのためBoostライブラリの利用者にはC++の現代的な記述に慣れていることを要求される。

 内容 
Boostには次のような分野のライブラリが含まれている。ヘッダーをインクルードするだけで使えるクラステンプレートや関数テンプレートが多いが、ライブラリの一部はビルドが必要。
 アルゴリズム
 ジェネレータ
 random - 疑似乱数
 uuid - UUID
 並列プログラミング（非同期プログラミング）
 thread - スレッド
 context - ユーザーレベルコンテキストスイッチ
 coroutine - コルーチン
 fiber - ファイバー
 compute - OpenCLベースのマルチコアCPU/GPGPU演算プラットフォームインターフェイス
 コンテナ
array - STLコンテナ方式による固定長配列の管理
Boost Graph Library (BGL) - 総称的グラフコンテナ、コンポーネント、アルゴリズム
multi-array - N次元配列の生成の単純化
multi-index containers - 異なるソートとアクセスセマンティクスを可能にするビルトインインデックスのあるコンテナ
pointer containers - 値へのポインタを素直に管理できるようにする標準的なSTLコンテナをモデルにしたコンテナ
property map - コンセプト的なインターフェイス仕様とキー値をオブジェクトにマップするための多目的インターフェイス
variant - コンパイル時に指定する型の集合から選べる型オブジェクトの効率的なストレージと、それにアクセスする型安全で総称的なスタックベースのオブジェクトコンテナ
any - あらゆる型の値を格納することができる動的型（ヘテロジニアスコンテナ）
 正当性とテスト
concept check - 指定可能なテンプレートパラメータ（コンセプト）を制限できるようにする
static assert - コンパイル時アサートのサポート
Boost Test Library - テストプログラムの作成、テストケースとテストスイートによるテストの構成、そしてそれらの実行制御のためのコンポーネントの組み合わせ。
 データ構造
dynamic_bitset - 動的なstd::bitset-に似たデータ構造
 関数オブジェクトと高階プログラミング （無名関数など）
bindとmem_fn - 関数、関数オブジェクト、関数ポインタおよびメンバ関数のための汎用バインダ
function - 遅延呼び出しのための関数オブジェクトのラッパー。コールバックのための汎用的なメカニズムも提供される。
functional - C++標準ライブラリで定義される関数オブジェクトのアダプタの強化。以下の内容を含む。
function object traits
negators
binders
adapters for pointers to functions
adapters for pointers to member functions
hash - C++ Technical Report 1 (TR1) で定義されているハッシュ関数オブジェクトの実装。ソートされていない連想コンテナのデフォルトのハッシュ関数として利用できる。
lambda - ラムダ抽象化の考え方で、プレースホルダー (placeholders) を使用して、小さい無名関数オブジェクトを定義できるようにする。特にアルゴリズムからの遅延呼び出しを使って、呼び出し地点でのこれらのオブジェクトの操作を可能とする。
ref - 標準C++の参照の能力を強化するため、特に関数テンプレートで利用するための、ユーティリティクラステンプレートを提供する。
result_of - 関数オブジェクトの戻り値の型を取り出す。関数の型を定義するのに役立つ。
signals2 - 管理されたシグナルとスロットのコールバック実装
 総称プログラミング
 Graphs 
 入出力
 言語間サポート（Python用）
 イテレータ
iterators
operators - ユーザー定義のイテレーターのための演算子をオーバーロードしてクラスが算術計算に適用できるようにするクラステンプレート。
tokenizer - シーケンス内に含まれるトークンのセットをコンテナとして見えるようにしてイテレーターでアクセスできるようにする。
 数学と計算
 QVM - 3次元コンピュータグラフィックスプログラミングで多用される固定サイズのクォータニオン、ベクトル、行列
 メモリ（参照カウントによるスマートポインタなど）
pool - 分割されたストレージベースのシンプルなメモリ管理スキームを提供する。
smart_ptr - 様々なポインタ管理方式によるスマートポインタクラステンプレートのコレクション。
scoped_ptr - ポインタ（単一のオブジェクト）を所有する。
scoped_array - 配列用のscoped_ptr。
shared_ptr - 他のshared_ptrと共有できるポインタ。最後のshared_ptrが破棄されたときにポインタを破棄する。
shared_array - 配列用のshared_ptr。
weak_ptr - すでにshared_ptrで管理されているオブジェクトへの「弱い参照」を提供する。
intrusive_ptr - ポインタが提供する参照カウンタを使用するshared_ptrに似たクラス。
utility - 以下のようなその他のクラス。
base from member idiom - 派生クラスのコンストラクタの初期化子でベースクラスのメンバを初期化する必要のあるクラスのための回避策を提供する。
checked delete - 不完全な型へのポインタを使用してオブジェクトまたはオブジェクトの配列を破棄しようとする試みをチェックする。
next and prior functions - 特に操作の結果が異なるイテレーターに保存されている必要がある（つまりオリジナルのイテレーターを変更できない）場合に、前方向または両方向のイテレーターをより簡単に操作できる。
noncopyable - コピーコンストラクタと代入演算子を禁止できる。
addressof - operator&()演算子のオーバーロードをバイパスしてオブジェクトの実際のアドレスを取得できるようにする。
result_of - 関数の型を定義するのに役立つ。
 
 構文解析
 プリプロセッサメタプログラミング
 文字列とテキスト処理（正規表現など）
lexical_cast - テキストとの型変換
format - タイプセーフな引数のフォーマット文字列
iostreams - 新しい送受信フィルタフレームワークのためのC++ストリームとストリームバッファの補助
regex, xpressive - 正規表現のサポート
Spirit - オブジェクト指向的な再帰的下向き構文解析ジェネレーターのフレームワーク。
string algorithms - 文字列に関する様々なアルゴリズムのコレクション。
tokenizer - 文字列やその他の文字シーケンスをトークンで分割できるようにする。
wave - C99/C++のプリプロセッサ機能の標準に準拠した実装。使いやすいインターフェイスでラップされている。
 テンプレートメタプログラミング
mpl - コンパイル時のアルゴリズム、シーケンス、メタ関数の、多目的で高レベルのメタプログラミングフレームワーク。
static assert - コンパイル時アサートのサポート
type traits - 基礎的な型の属性を定義するテンプレート。
 不完全なコンパイラの回避手段

 線型代数 
Boostには、BLASのレベル1、2、3の各演算を実装したuBLASという線型代数 (linear algebra) ライブラリがある。

 以下はベクトルと行列の乗算方法を表している。
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

using namespace boost::numeric::ublas;

/* "y = Ax" example */
int main()
{
 vector<double> x;
 x = 1; x = 2;

 matrix<double> A(2,2);
 A(0,0) = 0; A(0,1) = 1;
 A(1,0) = 2; A(1,1) = 3;

 vector<double> y = prod(A, x);

 std::cout << y << std::endl;
 return 0;
}

 乱数生成 
Boost.Random - 分布（ディストリビューション）非依存の擬似乱数生成器 (PRNG) と、具体的な生成器を構築するために組み合わせる疑似乱数に依存しない確率分布を提供する。

 以下はメルセンヌ・ツイスタ生成器を利用した正規分布によりサンプルする方法を表している。
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>

double SampleNormal(double mean, double sigma)
{
 // 非決定論的な乱数生成器をシードに使用。
 boost::random::random_device seed_gen;
 // メルセンヌ・ツイスタ乱数生成器の作成。
 typedef boost::random::mt19937 MyGenerator;
 MyGenerator rand_gen(seed_gen);

 // ガウス確率分布を選択。
 typedef boost::random::normal_distribution<double> MyDistribution;
 MyDistribution dist(mean, sigma);

 // 関数の形で乱数生成器を分布にバインドする。
 boost::random::variate_generator<MyGenerator&, MyDistribution> sampler(rand_gen, dist);

 // 分布からサンプルする。
 return sampler();
}

詳細はBoost Random Number Libraryを参照。

Boost.RandomのサブセットがC++11の標準ライブラリとして取り込まれた。

 テキストのパース 
Boost.Spirit - バッカス・ナウア記法に出来るだけ近いC++のプログラム形式で直接パーサを記述するという、Boostにおける最も複雑なライブラリのひとつ。
カンマ区切りの数値を読み込むパーサの例。

#include <boost/spirit/core.hpp>
#include <boost/spirit/actor/push_back_actor.hpp>
#include <iostream>
#include <vector>
#include <string>

using namespace std;
using namespace boost::spirit;

// Parser comma-separated numbers
bool parse_numbers(const char* str, vector<double>& v)
{
 return parse(str,
 // Start grammar
 (
 real_p[push_back_a(v)] >> *(',' >> real_p[push_back_a(v)])
 )
 ,
 // End grammar
 space_p).full;
}
詳細は Spirit User's Guide を参照。

 正規表現の利用 
Boost.Regex - 正規表現を利用するライブラリ。フィルタ・検索・パース・テキスト処理に必要な各種関数を持っている。

正規表現の種類としてPCRE、POSIX基本正規表現とPOSIX拡張正規表現が利用可能である。

 テキストをパースするプログラムの例。
#include <boost/regex.hpp>
#include <vector>
#include <string>

// Example program parsing the URL
int main(int argc, char** argv)
{
 // Check the number of parameters
 if (argc < 2) return 0;

 // container for the values
 std::vector<std::string> values;
 // Expression to parse
 boost::regex expression(
// proto host port
 "^(\?:([^:/\?#]+)://)\?(\\w+[^/\?#:]*)(\?::(\\d+))\?"
// path file parameters
 "(/\?(\?:[^\?#/]*/)*)\?([^\?#]*)\?(\\\?(.*))\?"
 );
 // The formation of the source string to parse (taken from command-line)
 std::string src(argv);

 // Parse and filling the container
 if (boost::regex_split(std::back_inserter(values), src, expression)) {
 // Output the result
 const char* names[] = {"Protocol", "Host", "Port", "Path", "File", "Parameters", NULL};
 for (int i = 0; names[i]; i++)
 printf("%s: %s\n", names[i], values[i].c_str());
 }
 return 0;
}
詳細は Boost.Regex を参照。

Boost.RegexのサブセットがC++11の標準ライブラリとして取り込まれた。

 動的な正規表現と静的な正規表現 
Boost.Xpressiveは、動的な正規表現と静的な正規表現を提供する。
以下のプログラムは「私は2052/10/30に生まれた。」という文字列に対し、年月日を抽出する正規表現である。どちらも出力結果は同じである。

 動的な正規表現 
#include <iostream>
#include <string>
#include <boost/xpressive/xpressive.hpp>

using namespace boost::xpressive;

int main()
{
	// 従来の char[] 型の文字列リテラルの内部表現は処理系依存であり、Shift_JIS の 0x5c など、場合によっては問題を引き起こす可能性があるため、UTF-8 文字列リテラルを使用するべき。
	// しかし C++20 以降は UTF-8 文字列リテラルの型が char8_t[] 型になるため、明示的なキャストが必要。
	// また、Microsoft Visual C++ 環境ではデフォルトで UTF-8 文字列をコンソールに出力できない。
	std::string str = "私は2052/10/30に生まれた。";

	sregex rx = sregex::compile(R"((\d{1,4})/(\d{1,2})/(\d{1,2}))");
	smatch m;

	if (regex_search(str, m, rx)) {
 // ここでは range-based for 構文を使っているので、C++11 以降に対応したコンパイラが必要。
 for (const auto& e : m) {
 std::cout << e << std::endl;
 }
	}
}

 静的な正規表現 
#include <iostream>
#include <string>
#include <boost/xpressive/xpressive.hpp>

using namespace boost::xpressive;

int main()
{
	std::string str = "私は2052/10/30に生まれた。";

	mark_tag years, month, days;

	sregex rx =
 (years = repeat<1, 4>(_d)) >> '/' >>
 (month = repeat<1, 2>(_d)) >> '/' >>
 (days = repeat<1, 2>(_d));

	smatch m;
	if (regex_search(str, m, rx)) {
 std::cout << m << std::endl;
 std::cout << m[years] << std::endl;
 std::cout << m[month] << std::endl;
 std::cout << m[days] << std::endl;
	}
}

 グラフのアルゴリズム 
Boost.Graph - グラフ理論の複数の視点および多数のアルゴリズムの形で、グラフ概念の柔軟かつ効果的な実装を提供する。
 アルゴリズムの例：トポロジカルソート
#include <iostream>
#include <list>
#include <algorithm>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/topological_sort.hpp>
#include <iterator>
#include <utility>

int main()
{
 using namespace boost;

 // Type of graph
 typedef adjacency_list<vecS, vecS, directedS, 
 property<vertex_color_t, default_color_type> > Graph;
 // Handle vertices
 typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
 // Container for the chain of vertices
 typedef std::vector<Vertex> container;
 // Type of representation of arcs
 typedef std::pair<std::size_t,std::size_t> Pair;

 // Edges of the graph 
 Pair edges = {
 Pair(0,1), Pair(2,4),
 Pair(2,5),
 Pair(0,3), Pair(1,4),
 Pair(4,3)
 };
 // Count
 Graph G(edges, edges + 6, 6);
 // Dictionary to get a handle on the numbers of vertices vertices
 boost::property_map<Graph, vertex_index_t>::type id = get(vertex_index, G);
 // Container for storing the sorted vertices
 container c;

 // Execute algorithm
 topological_sort(G, std::back_inserter(c));

 // Output results: sorting descriptors of the graph in the container,
 // Get the serial number of vertices
 std::cout << "Topological check:";
 for (container::reverse_iterator ii = c.rbegin(); ii != c.rend(); ++ii)
 std::cout << id[*ii] << " ";
 std::cout << std::endl;

 return 0;
}
詳細は The Boost Graph Library を参照。

 マルチスレッド 
Boost.Thread - プラットフォームに依存しないスレッドの抽象化を提供する。APIはPOSIXスレッドをベースにオブジェクト指向化したものとなっている。

 スレッドを生成しているコードの例。
#include <boost/thread/thread.hpp>
#include <iostream>

void hello_world()
{
 std::cout << "Hello world, I'm a thread!" << std::endl;
}

int main()
{
 // hello_world関数を呼び出す新しいスレッドを起動する。
 boost::thread my_thread(&hello_world);
 // スレッドが終了するまで待つ。
 my_thread.join();

 return 0;
}

Boost.ThreadのサブセットがC++11の標準ライブラリとして取り込まれた。

 Introduction to Boost.Threads in Dr. Dobb's Journal.
 Boost.Threads API reference.
 threadpool library based on Boost.Thread