boostメモ (format)

boost/format.hppは指定したフォーマットに従って文字列を生成するときに使える。
sprintfに近い印象だけど、char*とか出てこないから安全?
http://boost.cppll.jp/HEAD/libs/format/doc/format.html

なお、実行時に変な変換をすると例外を投げるので、死んだら困る業務プログラムとかだとちゃんと例外処理しないと痛い目を見ます。

### 追記 ###
"%1%"みたいに場所だけ指定して型を明示的に指定しない方法もある。


以下、サンプル。

/* -*- coding:utf-8 -*- */
/**
 * format.cpp
 */

#include <string>
#include <exception>
#include <boost/format.hpp>

int main() {
    std::cout << boost::format("%d + %d = %d") % 1 % 2 % 3 << std::endl;

    // stringに突っ込む場合はstrメソッドで変換が必要
    // std::string str = boost::format("%s%02d") % "hoge" % 1;
    std::string str = (boost::format("%s%02d") % "hoge" % 1).str();
    std::cout << "format_str = \"" << str << "\"" << std::endl;

    // 変換に失敗すると例外をあげるため、エラー時も継続して処理を続けるには適切にエラー処理が必要
    try {
        std::cout << boost::format("%s%02d") % "fuga"<< std::endl;
    } catch ( const std::exception& ex ) {
        std::cout << ex.what() << std::endl;
    }

    /*
     * 追記
     */
    // 型を明示的に指定しないでも使える
    std::cout << boost::format("%1% %2% %3%") % "puni" % 2012 % 3.1415 << std::endl;

    return 0;
}

$ g++ format.cpp
$ ./a.out
1 + 2 = 3
format_str = "hoge01"
boost::too_few_args: format-string referred to more arguments than were passed
puni 2012 3.1415

### 追記 ###
明示的に型を指定しない方法について、明示的に型を指定する場合との速度の違いが個人的に気になったので、簡単な時間計測のコードを書いてみた。
# 比較方法がテキトーなのは使用です。

比較では明示的に型を指定する場合と指定しない場合の双方について、それぞれ1,10,100,1000,10000回連続で実行した場合の実行時間を計測。各パターンはそれぞれ100回実行し、その平均値を実行時間とする。
なお、実行環境はMacBookAirで「1.6GHz Intel Core i5」。

/* -*- coding:utf-8 -*- */
/**
 * format_2.cpp
 */

#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <boost/format.hpp>

int main() {
    double msec_explicit, msec_implicit;
    clock_t begin, end;

    std::cout << "count\texplicit(msec)\timplicit(msec)" << std::endl;

    for (int i=0; i<5; i++) {
        uint64_t count = static_cast<uint64_t>(pow(10, i));

        // 明示的に型を指定した場合
        msec_explicit = 0.0;
        for (int j=0; j<100; j++) {
            begin = clock();
            srand(j);
            for (uint64_t k=0; k<count; k++) {
                boost::format("%d") % rand();
            }
            end = clock();
            msec_explicit += end - begin;
        }
        msec_explicit /= 100;
        // msecに修正
        msec_explicit = msec_explicit * 1000 / CLOCKS_PER_SEC;

        // 暗黙的に型を指定した場
        msec_implicit = 0.0;
        for (int j=0; j<100; j++) {
            begin = clock();
            srand(j);
            for (uint64_t k=0; k<count; k++) {
                boost::format("%1%") % rand();
            }
            end = clock();
            msec_implicit += end - begin;
        }
        msec_implicit /= 100;
        // msecに修正
        msec_implicit = msec_implicit * 1000 / CLOCKS_PER_SEC;

        std::cout << boost::format("%1%\t%2%\t\t%3%") % count % msec_explicit % msec_implicit << std::endl;
    }

    return 0;
}

$ g++ format_2.cpp
$ ./a.out
count explicit(msec) implicit(msec)
1 0.01472 0.01152
10 0.11472 0.07488
100 0.66532 0.61853
1000 6.38518 6.08243
10000 63.013 61.4699

結論:ほとんど差はない。
# 比較方法が悪い、実行回数が少ない、など色々問題ありですが
明示的に型を指定しない方が若干速く見えるけど、これは実行順序の影響とかを受けてる気がする。