The Debug class can act as an output stream for debugging and logging purposes. This is used e.g. for displaying custom messages in a failed DASSERT_MSG statement or for logging data.
There are a number of reasons why this module implements this in a stream-like fashion instead of the 'usual' printf method:
- type safety: using a streams-like approach makes logging statements type safe. No more crashes in an ASSERT or log statement because the parameter specifiers in the printf format string didn't match with the values actually given.
- extensibility: new stream operators can be implemented outside of the debug module
Syntactically the Debug class acts almost like a ostream class:
int n=1;
float f=4;
DLOG(
"This is a static string and some other stuff: "
<< n << " " << f << "\n" );
New types can be added easily, e.g.:
{
debug << "(" << pt.x << ";" << pt.y << ")";
return debug;
}
{
DLOG(
"Current point value is " << val <<
"\n" );
DASSERT_MSG( val.x>=0 && val.y>=0, val <<
" is invalid");
}
Debug module main class (singleton).
#define DASSERT_MSG(expr, msg)
Debug & operator<<(Debug &dbg, const DebugStackwalk::Signature &sig)
Dumps a complete signature with symbols.
Please note that all these operators should not be cluttered with any #ifdef _DEBUG or similar conditional compile statements. It is not necessary to remove these operators from the code in release builds (just don't forget to add 'inline' before the operator though).
In addition there are a number of helper classes declared inside of Debug:
- Debug::MemDump provides functions for inserting a raw memory dump into the Debug stream
- Debug::HResult dumps out a HRESULT value plus additionally calling custom translator functions