boostライブラリについて
ライブラリ†
個人的には一番よく使うのがboost::bind.
STLのbind1st, bind2stの汎用版である.任意の引数をbindして,固定値にしたり,メンバ関数へのポインタもサポートする.
#include <boost/bind.hpp>
boost::bindは関数オブジェクトを作成することができるのだが,関数の引数をある値に固定することができる.
例えば,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| | int func2(int x, int y)
{
return x+y;
}
int func3(int x, int y, int z)
{
return x+y+z;
}
void main(void)
{
boost::function<int (int, int)> func;
func = func2;
cout << func(1, 2) << endl;
func = boost::bind(func3, _1, _2, 0);
cout << func(1, 2) << endl;
}
|
のように,3引数を取る関数の最後の引数に渡す値を0に固定した関数の関数オブジェクトを簡単に作れる.
また,下のboost::functionでも述べているが,メンバ関数についても下記のmem_fnと同様にできる.
1
2
| | Class1 *obj = new Class1;
boost::function<int (int)> func = boost::bind(&Class1::Func1, boost::ref(obj), _1);
|
#include<boost/mem_fn.hpp>
メンバ関数を関数オブジェクトとして扱えるようにする.std::mem_fun,std::mem_fun_ref の一般化バージョンで引数の数は2個以上でも可能.std::for_eachにメンバ関数を渡したいときなどに便利.
class MemClass
{
public:
MemClass(int x) : a(x){}
void Print(){ cout << a << endl; }
private:
int a;
};
void main(void)
{
vector<MemClass> v;
v.push_back(MemClass(1));
v.push_back(MemClass(2));
v.push_back(MemClass(3));
for_each(v.begin(), v.end(), boost::mem_fn(&MemClass::Print));
}
#include<boost/lexical_cast.hpp>
文字列と値の変換を行う.C言語のitoaとかと同じ.
double x = 0.0;
std::string str;
str = boost::lexical_cast<std::string>(x);
x = boost::lexical_cast<double>(str);
#include<boost/format.hpp>
printfに似たような感じの書式化処理をする.
cout << boost::format("i : %1% - x=%2%, str=%3%") % 1 % 15.0 % "rml";
formatではformatオブジェクト(フォーマッタ)にオペレータ"%" で変数を食わせるため,
boost::format frmt("i : %1% - x=%2%, str=%3%");
frmt % 1;
frmt % 15.0;
frmt % "rml";
でも可.std::stringではき出したい場合は,メンバ関数str()かboost::ioのstr(const format&)を用いる.
std::string str;
str = frmt.str();
str = boost::io::str(frmt);
フォーマッタに別の変数を食わせる場合は,そのまま,
frmt % 2;
frmt % 20.0;
frmt % "rml2";
と続ける.
書式指定に%1%,%2%・・・を用いる場合は並べ替えが可能.
cout << boost::format("%2%, %1%, %3%, %1%") % 1 % 2 % 3;
出力は 2, 1, 3, 1 となる.並び替えが必要でないなら従来のprintf通りの書式指定を用いることもできる.
cout << boost::format("%d, %s, %3.1f") % 1 % "2" % 3.0;
出力は 1, 2, 3.0 .
#include<boost/function.hpp>
汎用関数オブジェクト.関数ポインタも関数オブジェクトも両方とも格納できる.
class FuncClass
{
public:
FuncClass(int i, int j) : a(i), b(j) {}
double Dot(int x, int y){ return sqrt((double)(a*x+b*y)); }
int a, b;
};
struct FuncObject
{
double operator()(int x, int y){ return sqrt((double)(x*x+y*y)); }
};
double Func(int x, int y)
{
return sqrt((double)(x*x+y*y));
}
とあった場合,関数ポインタ(Func(int x, int y))では,
boost::function<double (int, int)> length = &Func;
cout << boost::format("length = %f\n") % length(1, 2);
で出力は,length = 2.236068 となる.function<double (int, int)>でdoubleが返値,(int, int)が引数を表している.コンパイラによっては,function2<double, int, int> と書かなければならないかも.
関数オブジェクト(FuncObject)は,
length = FuncObject();
cout << boost::format("length = %f\n") % length(2, 3);
出力は,length = 3.605551 となる.
クラスのメンバ関数を渡すときは,std::mem_fun と std::bind1st あたりを用いることができるが,ここでは2変数をとっているので boost::bind を用いる.
FuncClass obj(3, 4);
length = boost::bind(&FuncClass::Dot, boost::ref(obj), _1, _2);
cout << boost::format("length = %f\n") % length(3, 4);
出力は,length = 5.000000 となる.
#include <boost/xpressive/xpressive.hpp>
正規表現クラス.boost::regexと違ってlibファイルは必要ない.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| |
static bool Match(const string &str, const string ®_str)
{
using namespace boost::xpressive;
sregex reg = sregex::compile(reg_str);
smatch m;
if(regex_search(str, m, reg)){
return (m.str() == str);
}
else{
return false;
}
}
static bool Match2(const string &str, const string ®_str, vector<string> &mch)
{
using namespace boost::xpressive;
sregex reg = sregex::compile(reg_str);
smatch m;
if(regex_search(str, m, reg)){
mch.resize(m.size());
for(int i = 0; i < (int)mch.size(); ++i){
mch[i] = m[i];
}
return (m.str() == str);
}
else{
return false;
}
}
|
#include <boost/random.hpp>
様々な乱数を生成する.以下はメルセンヌツイスタで正規乱数,定分布乱数を生成するジェネレータの例.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| | typedef boost::variate_generator< boost::mt19937, boost::uniform_real<> > rxRandMtUni;
typedef boost::variate_generator< boost::mt19937, boost::normal_distribution<> > rxRandMtGen;
inline rxRandMtGen GenRandomGenerator(const double &_min, const double &_max)
{
boost::mt19937 gen0(static_cast<unsigned long>(time(0)));
boost::normal_distribution<> dst0(0, 0.01);
rxRandMtGen rand0(gen0, dst0);
return rand0;
}
inline rxRandMtUni GenRandomGeneratorMtUni(const double &_min, const double &_max)
{
boost::mt19937 gen0(static_cast<unsigned long>(time(0)));
boost::uniform_real<> dst0(_min, _max);
rxRandMtUni rand0(gen0, dst0);
return rand0;
}
|
使うときは,
rxRandMtGen rand = GenRandomGenerator(0.0, 1.0);
for(int i = 0; i < 100; ++i){
cout << rand() << endl;
}
など.
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/operations.hpp>
など.
オリジナルのストリームを作成することができる.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
| | class rxCout : public boost::iostreams::sink
{
string m_strLog;
public:
rxCout(string fn)
{
m_strLog = fn;
}
std::streamsize write(const char* s, std::streamsize n)
{
string str; str.resize(n);
for(int i = 0; i < n; ++i){
str[i] = s[i];
}
cout << str;
boost::algorithm::replace_all(str, "\n", "");
static std::ofstream fsOut(m_strLog, std::ios::out);
fsOut << str << endl;
return n;
}
};
static boost::iostreams::stream<rxCout> RXCOUT("test.log");
class rxCoutFile : public boost::iostreams::sink
{
public:
rxCoutFile(bool enable)
{
}
std::streamsize write(const char* s, std::streamsize n)
{
string str; str.resize(n);
for(int i = 0; i < n; ++i){
str[i] = s[i];
}
boost::algorithm::replace_all(str, "\n", "");
static std::ofstream fsOut("log/sph.log", std::ios::out);
fsOut << str << endl;
return n;
}
};
static boost::iostreams::stream<rxCoutFile> RXFOUT(true);
|
例のRXCOUTをcoutの代わりに使うことで出力内容を画面に表示すると共にファイルにも保存することができる.
boost::filesystem†
v3での変更点†
- 1バイト文字のpathと2バイト文字のwpathを,一つのクラスpathに統合.
- pathクラスの新しいメンバ関数
- boost::filesytem関数の変更,新規追加
詳しくはBoost Filesystem Version 3 - Introduction.
Visual C++でのインストール†
Visual C++用のバイナリがboostproで配布されている(要登録).
自身の環境でビルドしたい場合の手順は以下
(詳しくは,Getting Startedを参照).
- boostのページから最新のboostライブラリをダウンロードする.
中央のDOWNLOADSのところから最新版のリンクをクリックし,boost_1_57_0.zipなどをダウンロードして解凍する.
解凍先フォルダを$BOOSTとする.
[ver1.5?以降(バージョンはちゃんと確かめていない)]
- boostではビルドするためのBoost.Buildシステムを構築するためのバッチファイルbootstrapが含まれているので,これを実行する.
スタートメニューからVisual Studioコマンドプロンプト
(VS2012ならMicrosoft Visual Studio 2012 -> Visual Studio Tools -> VS2012 の開発者コマンド プロンプト)
を立ち上げ,$BOOSTフォルダに移動し,以下のコマンドを実行すr.
bootstrap
- Boost.Buildシステムが構築されたら以下のコマンドを実行
.\b2
ビルドオプションはb2 --helpで確認できる.例えばx64,multi-threadingで4スレッドでビルドの場合ならば,
.\b2 threading=multi variant=debug,release address-model=64 -j 4
となる.static,sharedはlink,runtime-linkオプション,作成されたライブラリファイルを置くフォルダ指定には--stagedirオプションを用いる.
[ver1.49?以前]
- bjam.exeを準備する.boostのページからビルド済みバイナリを落としてくるか,
自分で環境に合わせてビルドする.ビルドの仕方は以下.
$BOOST\tools\jam\src\build.bat を実行する. bjamのソースコード(boost-jam-3.1.18.zipなど)をダウンロード解凍する.解凍したフォルダにあるbuild.batを実行する.何も指定しなければ自動で環境を判別する.環境を選択する場合は,コマンドプロンプトから,
build.bat vc10
などとする.vc10はVS2010, vc8にするとVS2005, vc9にするとVS2008.その他のtoolsetはBuilding BJamを参照.
- $BOOST\tools\jam\src\bin.ntx86\ に環境に合わせたbjam.exeができるので,これを$BOOSTかPATHが通っているところに移動.
- コマンドプロンプトで$BOOSTに移動して,bootstrap.batを実行.
bootstrap.bat
- bjam.exeを実行する.オプションの例は以下.
bjam.exe --toolset=msvc-10.0 --prefix=C:\usr\boost_1_45 --build-type=complete link=static release install
オプションとして,
- --toolset=msvc-10.0 : VS2010用,VS2005の場合はmsvc-8.0,VS2008の場合はmsvc-9.0
- --prefix=C:\usr\boost_1_45 : インストール先.インクルードファイルとライブラリファイル(*.lib)などが置かれる.
- --build-type=complete : 完全ビルド.デフォルトではminimalになっている.
- link=static : スタティックリンクを指定(dllなし).共有リンクの場合はsharedを指定,両方指定(link=static,shared)も可
- release : リリースビルド.デバッグビルドの場合はdebugを指定する.
- install : ビルドしたファイル(*.dll, *.libなど)をprefixで指定したフォルダに移動する.
を指定している.他のオプションの詳しい説明は bjam.exe --help で参照.ビルドは環境にもよるが結構時間がかかるので注意.
- prefixオプションで指定したところにinclude\boost-1_45, libフォルダができているので,それぞれインクルードパス,ライブラリパスに追加するなどする.
リンク†