3

デバッグ、情報などのメッセージ用にさまざまなメソッドを持つカスタム ロガー クラスがあります。ログメッセージのほかに、ロガーメソッドが呼び出されたファイルの名前と行、およびタイムスタンプも出力したいと思います。

私が今持っている解決策は次のようなものです:

m_logger.debug("some debug message", __FILE__ , __LINE__, __TIME__);

質問: 2 つのマクロの呼び出しを回避し、自動的に呼び出されるように実装する方法はあり__FILE__ますか__LINE__?__TIME__

ありがとう。

4

4 に答える 4

10

おそらくこのようなもの:

#define debug_with_ft(x) debug(x, __FILE__, __TIME__)

...
m_logger.debug_with_ft("some debug message");

もちろん、これを解決するにはさまざまな方法があります。たとえばm_logger、マクロで全体を非表示にします。

#define debug_with_ft(x) m_logger.debug(x, __FILE__, __TIME__)
于 2013-02-28T11:51:24.790 に答える
4

__TIME__コンパイル時に現在時刻を生成するプリプロセッサ マクロです。したがって、おそらく実行時(メッセージがログに記録されるとき) に現在の時刻にアクセスする必要があるため、このケースでは使用しないでください。

__FILE__もプリプロセッサ マクロであり、プリコンパイル時に評価する必要があります。別の方法で実装することはできません。

__LINE__マクロにも興味があるかもしれません

于 2013-02-28T11:57:17.047 に答える
2

これは、マクロ正しい解決策である 1 つのケースです。マクロを使用してロガーを呼び出したい (マクロだけが__FILE__andを自動的に挿入できる__LINE__ため)、クライアント コードが 1 つまたは複数のメッセージ要素を渡すことができるようにする方法で、おそらく<<. これを行う通常の方法は、次のようなものです。

#define LOG() m_logger.getStream( __FILE__, __LINE__ )

、ここでm_logger.getStreamヘッダーを挿入し (その引数と現在の時刻を使用)、ログ ストリームへの参照、または実装も行う特別なラッパー クラスのいずれかを返します — ストリームへの参照を返す<<だけが最も簡単ですが、ラッパーを使用するとメッセージの終わりをキャッチする (ラッパーは一時的なものであり、完全な式の最後で破棄されるため)、取り込まれたロックを解放するgetStream(ロギングがスレッドセーフになるように)、または出力がアトミックであることを確認する、そして<<ラッパーが次のようなものである場合:

template <typename T>
LogStream& LogStream::operator<<( T const& object )
{
    if ( myStream != NULL ) {
        *myStream << object;
    }
}

、ログを無効にすることができ、無効になっている場合は変換を行いません。

于 2013-02-28T12:12:11.087 に答える
1

なぜあなたは考え__FILE____TIME__悪いのですか?それらが本当にマクロそのものであるかどうかはわかりません。それらはいわゆるマクロ名です。また、それらは標準で定義されていると思うので、安全で使用しても問題ないはずです。

余談ですが、コンパイル時の評価と実行時の評価の概念を見逃しているようです。

実行時にソースファイルの名前をどのように知ることができますか? そのため__FILE__、コンパイラがファイル名を評価するので、 を使用する必要があります。

__TIME__に、マクロ名もコンパイラによって置き換えられます。行がコンパイルまたは呼び出された時刻をログに記録しますか? 後者の場合は、適切なランタイム関数を使用する必要があります。

回りきる可能性は無いと思います__FILE__

ただし、通話を短くしたい場合は

次のスニペットを使用します。

#ifndef NDEBUG
#define DEBUG_MSG(msg) do{ std::cerr << __FILE__ << "(@" << __LINE__ << "): " << msg << '\n'; } while( false )
#else
#define DEBUG_MSG(msg) do{ } while ( false )
#endif

非常に移植性が高く使いやすいと思いますが、クラス メソッドとして使用するためのものではありません。おそらく次のように定義できます

#define DEBUG_MSG(msg) debug( msg, __FILE__, __LINE__ )

のように使用します

m_logger.DEBUG_MSG("message");

そのため、マクロは設計された関数呼び出しに展開されます。ただし、かなり危険です。署名を変更debugすると、マクロを変更する必要があり、移植性がほとんどありません。

于 2013-02-28T11:56:06.727 に答える