4

このような構造が散りばめられたコードがいくつかあります

if(debug) {
    Output << "f1: " << f1() << "\n";
}

今私がやりたいことは、Debugこのように書くことができるストリームクラスを書くことです

Debug << "f1: " << f1() << "\n";

グローバル フラグが設定されている場合、出力が生成されますが、そうでない場合は生成されません。

これは、出力を飲み込む先のDebugストリームを return にすることで、非常に簡単に実行できます。/dev/null問題は、f1()依然として評価される (そして、さらにコストがかかる可能性のあるテキスト表現に「レンダリング」される) ことであり、これはパフォーマンスにとって非常に悪い可能性があります。

ここで私の質問:「評価」のスキップを可能にするトリックはありますか?

"f1: " << f1() << "\n"

出力を行わないと決定した場合は完全Debugに? f() && g()C++ がwhere g()is not evaluate if f()isに対して行うショート サーキットと同様ですfalse(出力演算子として使用するストリーム クラスを作成することを真剣に検討しました&&が、読んだ内容からは、オーバーロードされたショート サーキットは実行されませんoperator&&) 。

4

3 に答える 3

5

あなたができることは、このマクロを定義することです:

#define Debug_Stream \
if(!debug); else Output

これにより、次のようになります。

Debug_Stream << "f1: " << f1() << "\n";

これと同等になります:

if(debug) {
    Output << "f1: " << f1() << "\n";
}

ただし、文字通り(読みやすくするための空白を追加)

if(!debug);
else
    Output << "f1: " << f1() << "\n";
于 2012-08-06T17:36:16.183 に答える
4

マクロに反対ではなく、構文を受け入れる意思がある場合:

Debug( "f1: " << f() << '\n' );

それは非常に簡単です: 次のように定義するだけです:

#define Debug( x ) debug != NULL && *debug << x;

ただし、引数を括弧で囲むという通常の予防策を講じることができないため、多少危険です。(一方で、多くのアプリケーションで問題なく使用されているのを見てきました。) マクロ アプローチには、必要に応じて自動的に挿入できるという利点もあり __FILE__ます__LINE__または、条件付きですべてのコードを完全に抑制するには、マクロを何も定義しないようにします。

于 2012-08-06T17:35:53.753 に答える
2

高価な関数呼び出しをラップする遅延エバリュエーターを作成することで、これを行うことができると思います。ストリームは、参照された関数を呼び出す必要がある遅延エバリュエーター タイプを認識しますが、それ以外の場合は no-op で、高価な呼び出しを防ぎます。no-debug ストリームは、プロキシ エバリュエーター オブジェクトが評価を完全にスキップすることを認識しています。

たとえば、呼び出しは次のようになります。

Debug << "123" << delay(f()) << "456" << std::endl;

これには、デバッグ行で遅延を呼び出すことを忘れないでください。あなたのケースでは重要な問題であるかもしれないし、そうでないかもしれないマクロの必要性を避けます。

于 2012-08-06T17:41:35.187 に答える