ログ出力

最近になって std::clog の存在を知った.「バッファ付き標準エラー出力」だそうな.ってことは std::coutstd::cerr と合わせて 3 つの出力先を使い分けられるじゃん.よぅし.
ということで,こんな使い方を提案.

目的
コマンドライン引数 -v (verbose の意) が指定された時のみ,ログファイル (verbose.log など) に処理過程のログを出力する.ログとエラーメッセージは別物として扱いたい.こうしたいのは俺だけかねぇ….
実装例
main() 内部での記述を想定し,必要となる部分だけ書いた.

std::string   logfile = "/dev/null";  // UNIX 環境の場合
//std::string logfile = "nul";        // Windows 環境の場合
std::ofstream ofsLog;

while ((opt = getopt(argc, argv, "v")) != -1)
{
    switch (opt)
    {
        case 'v':
            logfile = "verbose.log";
            break;
    }
}

ofsLog.open(logfile.c_str());
if (ofsLog.fail())
{
    std::cerr << "ERROR: can't open log file." << std::endl;
}
std::clog.rdbuf(ofsLog.rdbuf());

// あとは
std::clog << "ログ" << std::endl;
std::cerr << "エラーメッセージ" << std::endl;
// というように使い分ける.

ofsLog.close();    // main() の最後にクローズ
実行例
上記のような実装を施したプログラムの名前を logtest とする.

$ ./logtest -v > output.txt 2> error.txt
上記のようにプログラムを実行すれば,実行結果 (たいていは標準出力に出力されるだろう) は output.txt に,エラーメッセージ (たいていは標準エラー出力に出力されるだろう) は error.txt に,ログは verbose.log に,それぞれ書き出される.
ログファイルにもエラーメッセージを書き出したいのであれば,そのようにソースを書き直す必要がある.その場合,同じメッセージを std::cerr にも std::clog にも書き出すわけだから,ソースの上ではなんかスッキリしない気も.

verbose フラグなるものを用意して ソースの至る所に if 文を書く よりはスッキリするかなぁと思って書いてみた.バグなどを発見したらぜひご連絡を.