printf()
usingへのすべての呼び出しを削除できます#define printf
。のようなデバッグ出力がたくさんある場合はどうすればよいstd::cout << x << endl;
ですか? cout <<
プリプロセッサを使用して単一ファイル内のステートメントをすばやくオフにするにはどうすればよいですか?
7 に答える
「巻き戻し」が既に述べたように、迅速な解決策は何もしないストリームです。ただし、より良い実装があります。
class NullStream {
public:
NullStream() { }
template<typename T> NullStream& operator<<(T const&) { return *this; }
};
これは 3 つのトークンのシーケンスであるため、まだわずかな問題があり、個別にstd::cout
再定義する必要はありません。簡単な解決策はstd
cout
#ifdef NDEBUG
#define COUT std::cout
#else
#define COUT NullStream()
#endif
COUT << "Hello, world" << std::endl;
一般的な原則として、stdout へのログ記録は避けるべきです。ログファイルにログを記録する方がはるかに優れています。その後、標準の構成ツールを使用してログ レベルを変更したり、完全にオフにしたりできます。
ちょうど私の$ 0.02.....
デバッグ出力ステートメントを次のように置き換えます。
IFDBG(cout << result << endl);
次に、それに応じてマクロを定義できます。
#ifdef DEBUG
# define IFDBG(x) x
#else
# define IFDBG(x)
#endif
このマクロを定義します:
#ifdef DEBUG
#define MY_LOG std::cout
#else
#define MY_LOG if(false) std::cout
#endif
このマクロの利点は、コンパイラの最適化にあります
これらの IF 内に配置された式がコンパイル時に定数で決定可能である場合、コンパイラがコードからそれらを既に削除していることはほぼ確実です... https://stackoverflow.com/a/14657645/5052296
NullStream は、デバッグ ステートメントをすばやく削除する方法を探している場合に適したソリューションです。ただし、デバッグ用に独自のクラスを作成することをお勧めします。これは、より多くのデバッグ機能が必要な場合に必要に応じて拡張できます。
class MyDebug
{
std::ostream & stream;
public:
MyDebug(std::ostream & s) : stream(s) {}
#ifdef NDEBUG
template<typename T>
MyDebug & operator<<(T& item)
{
stream << item;
return *this;
}
#else
template<typename T>
MyDebug & operator<<(T&)
{
return *this;
}
#endif
};
これは、最初に必要なことを実行できる単純なセットアップであり、デバッグ レベルなどの機能を追加できるという追加の利点があります。
更新: マニピュレータは関数として実装されているため、マニピュレータも受け入れたい場合 (endl) を追加できます:
MyDebug & operator<<(std::ostream & (*pf)(std::ostream&))
{
stream << pf;
return *this;
}
そして、すべてのマニピュレータ タイプに対して (すべてのマニピュレータ タイプに対してオーバーロードする必要がないように):
template<typename R, typename P>
MyDebug & operator<<(R & (*pf)(P &))
{
stream << pf;
return *this;
}
通常の関数ポインタも受け入れるため、この最後のものには注意してください。
cerr
おそらく、何もしないという名前のインスタンスを使用して、新しいストリームのようなクラスを定義するプリプロセッサ ハックを実行できます。本当に運が良ければ、コンパイラは関数が何もしないことを認識し、operator<<()
out の呼び出しを最適化します。
何かのようなもの
class NullStream
{
public:
NullStream();
NullStream& operator<<(const std::string& text) { return *this; }
// And operators for other types, too
}
static NullStream cerr;
ただし、これは非常にハックです。ソースを調べて、ログの適切なサポートを追加する方が (はるかに) 優れています。
置き換えるマクロを定義することはcout
、VCS にアップロードする必要はありませんが、デバッグ中に一時的に行うだけであれば、その役割を果たしていると思います。cout
したがって、次のostream(0)
ように置き換えることができます
#ifdef NDEBUG
#define cout ostream(0).flush()
#endif
このように、 と plain の両方で動作し、をstd::cout
含む場合に使用できます。a への書き込みはノーオペレーションです。関数呼び出しは、それへの非 const 参照を取得するように行われます (したがって、出力などに使用される非メンバーにもバインドされます)。その型はであるため、 とまったく同じように動作する必要があります。cout
ostream
<iostream>
ostream(0)
flush
operator<<
std::string
ostream
cout