1

次の特性を持つロギング機能を設計したいと考えています。

  • char* ではなく std::string に基づく
  • printf のように可変数の変数をサポート
  • 最初のパラメーターとして重大度レベルを受け入れます
  • 重大度レベルがロギング レベルを下回る場合のフォーマット オーバーヘッドを回避
  • printf と同じか、それに近い単純さ

自動型変換のため、boost::format を使用する傾向があります。しかし、ここに私が見るいくつかの問題があります:

その構文は少しぎこちなくformat("Mgr %s on pid %d is in state %s" % mgr % pid % s)、目には少し難しいです (変数のリストの性質は、コンマなしでは明らかではありません)。ログ呼び出しは次のようになります。

mylog(INFO, format("Mgr %s on pid %d is in state %s" % mgr % pid % s));

さらに悪いことに、mylog() を実装して、フォーマット オブジェクトが構築さ れる前に INFO メッセージをログに記録しているかどうかを確認することさえ可能ですか?

私が考えたもう1つのアプローチは、printfに近いように見えますが、

mylog(INFO, "Mgr %s on pid %d is in state %s", mgr, pid, s);

あるいは

mylog_info("Mgr %s on pid %d is in state %s", mgr, pid, s);

実装は次のようになります。

mylog(int severity, string pattern, ...) {
    if (severity >= LOGLEVEL) {
        boost::format fmt(pattern);
        for parm /* remaining parameters */ {
            fmt % parm; // feed into format one at a time
        }
    }
}

これにより、必要になるまでフォーマットオブジェクトの構築が確実に延期されます。しかし、私が知る限り、可変引数リストをトラバースするときに、最後に到達したことを知る方法はありません!

誰かがこれを達成するための構文的に簡単なテクニックを提案できますか?

注: 私は g++ 4.4 を持っていますが、これは c++11 のすべてをサポートしているわけではありません (ただし、可変個引数テンプレートはサポートしています)。

4

2 に答える 2

1

可変個引数テンプレートと再帰を使用できます。

注: GCC 4.4について言及しているため、この機能はそのコンパイラで利用できますが、デフォルトでは有効になっていません。この機能を有効にするには、コンパイラに-std=c++0xorオプションを追加する必要があります。-std=gnu++0x

ソリューションは、次のようなものとして実装できます。

// Does the actual logging of the formatted message
void mylog_r (int severity, boost::format &fmt) {
  std::cout << "[" << severity << "] "
            << fmt
            << std::endl;
}

// Unpacks the variadic arguments one at a time recursively
template <typename T, typename... Params>
void mylog_r (int severity, boost::format &fmt, T arg, Params... parameters) {
  mylog_r(severity, fmt % arg, parameters...); // recursively unpack
}

// This version of mylog() checks severity and converts fmt to boost::format
template <typename... Params>
void mylog (int severity, std::string fmt, Params... parameters) {
  if (severity < LEVEL) return;
  boost::format bfmt(fmt);
  mylog_r(severity, bfmt, parameters...);
}
于 2013-08-21T03:21:37.300 に答える