Heavy Watal

Boost — ほぼ標準C++ライブラリ

Installation

パッケージマネージャで

Homebrew で最新版を簡単にインストールできる。 オプションは適当に:

brew install boost

--layout=tagged でビルドされるため、 リンクするときは末尾に -mt が必要になる。

ソースから

  1. https://www.boost.org/users/download/ から最新ソースを入手して展開。

    wget -O- https://dl.bintray.com/boostorg/release/1.67.0/source/boost_1_67_0.tar.bz2 | tar xj
    cd boost_1_67_0/
    
  2. ビルドすべきライブラリを考える ./bootstrap.sh --show-libraries

  3. 適当なオプションを与えて bootstrap.sh を実行:

    ./bootstrap.sh --help
    ./bootstrap.sh --without-icu --with-libraries=context,filesystem,graph,iostreams,program_options,serialization,system,test
    

    設定が project-config.jam に書き出され、 b2 がビルドされる。 ./b2 --help

  4. ~/user-config.jam に [ツールセットを定義] (https://www.boost.org/build/doc/html/bbv2/reference/tools.html)。 darwinはMac-gcc用:

    using gcc : 14 : g++-8 : <compileflags>-fPIC <cxxflags>-std=c++14 ;
    using darwin : 14 : g++-8 : <compileflags>-fPIC <cxxflags>-std=c++14 ;
    using clang : 14 : clang++ : <compileflags>-fPIC <cxxflags>-std=c++14 -stdlib=libc++ <linkflags>-stdlib=libc++ ;
    

    gccとclangの両方から使える統一ライブラリを作るのは難しいらしいので、 それぞれのコンパイラで別々にビルドしてインストールする。

  5. システム標準zlibをリンクしようとしてエラーになるような場合は、 zlib公式からソースを落として展開し、 [一緒にビルドされるように] (https://www.boost.org/doc/libs/release/libs/iostreams/doc/installation.html) ZLIB_SOURCEをフルパス指定する。

    wget -O- https://zlib.net/zlib-1.2.8.tar.gz | tar xz -C ${HOME}/tmp/build
    export ZLIB_SOURCE=${HOME}/tmp/build/zlib-1.2.8
    
  6. ツールセットを指定してビルド:

    ./b2 -j2 toolset=gcc-14 link=static,shared runtime-link=shared threading=multi variant=release --layout=tagged --build-dir=../b2gcc --stagedir=stage/gcc stage
    ./b2 -j2 toolset=darwin-14 link=static,shared runtime-link=shared threading=multi variant=release --layout=tagged --build-dir=../b2gcc --stagedir=stage/gcc stage
    ./b2 -j2 toolset=clang-14 link=static,shared runtime-link=shared threading=multi variant=release --layout=tagged --build-dir=../b2clang --stagedir=stage/clang stage
    
  7. prefixを指定してインストール:

    ./b2 -j2 toolset=gcc-14 link=static,shared runtime-link=shared threading=multi variant=release --layout=tagged --build-dir=../b2gcc --stagedir=stage/gcc --prefix=${HOME}/local install
    

    あるいは手動でインストール:

    rsync -auv stage/gcc/ ~/local/boost-gcc
    rsync -auv stage/clang/ ~/local/boost-clang
    rsync -auv boost ~/local/include
    

使うとき

インストールした場所とリンクするライブラリをコンパイラに伝える必要がある。 コマンドを直打ちするなら:

clang++ -I${HOME}/local/include -L${HOME}/local/lib mysource.cpp -lboost_iostreams-mt -o a.out

Makefileの変数でいうと:

CPPFLAGS = -I${HOME}/local/include
LDFLAGS = -L${HOME}/local/lib
LDLIBS = -lboost_iostreams-mt

CMakeでは BOOST_ROOT にprefixを指定:

cmake -DBOOST_ROOT=${HOME}/local ..

math

https://www.boost.org/doc/libs/release/libs/math/

distribution

https://www.boost.org/doc/libs/release/libs/math/doc/html/dist.html

確率分布に従った乱数生成はC++11から <random> でサポートされるようになったが、 確率密度関数(PDF)や累積密度関数(CDF)はまだ標準入りしてない。

// #include <boost/math/distributions.hpp>
#include <boost/math/distributions/normal.hpp>
#include <boost/math/distributions/poisson.hpp>
#include <boost/math/distributions/binomial.hpp>
#include <boost/math/distributions/chi_squared.hpp>

namespace bmath = boost::math;

bmath::normal_distribution<> dist(mean, sd);

bmath::mean(dist);
bmath::median(dist);
bmath::standard_deviation(dist);

bmath::pdf(dist, x);
bmath::cdf(dist, x);
bmath::quantile(dist, p);

右側の裾が欲しいときは精度を保つために complement() を使う。 (Rでいう lower.tail=FALSE)

// good
bmath::quantile(bmath::complement(dist, p));
// bad
bmath::quantile(dist, 1.0 - p)

// good
bmath::cdf(bmath::complement(dist, x));
// bad
1.0 - bmath::cdf(dist, x);

iostreams

https://www.boost.org/doc/libs/release/libs/iostreams/doc/

要ビルド&リンク -lboost_iostreams-mt

gzip 圧縮と展開

#include <iostream>
#include <string>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

int main() {
    namespace bios = boost::iostreams;
    {
        bios::filtering_ostream ost;
        ost.push(bios::gzip_compressor());
        ost.push(bios::file_descriptor_sink("hello.txt.gz"));
        ost << "Hello world!";
    }
    {
        bios::filtering_istream ist;
        ist.push(bios::gzip_decompressor());
        ist.push(bios::file_descriptor_source("hello.txt.gz"));
        std::string buffer;
        std::getline(ist, buffer, '\0');
        std::cout << buffer << std::endl;
    }
}

program_options

https://www.boost.org/doc/libs/release/libs/program_options/

要ビルド&リンク -lboost_program_options-mt

cf. getopt

coroutine2

https://www.boost.org/doc/libs/release/libs/coroutine2/

要ビルド&リンク -lboost_context-mt

PythonのyieldみたいなことをC++でもできるようになる。

example of Fibonacci generator

オブジェクトの寿命に注意。

そのほか

<boost/multiprecision/cpp_int.hpp>

<boost/dynamic_bitset.hpp>