A prettier method:
#ifdef _DEBUG
#define DBOUT cout // or any other ostream
#else
#define DBOUT 0 && cout
#endif
DBOUT << "This is a debug build." << endl;
DBOUT << "Some result: " << doSomething() << endl;
As long as you don't do anything weird, functions called and passed to DBOUT
won't be called in release builds. This macro works because of operator precedence and the logical AND; because &&
has lower precedence than <<
, release builds compile DBOUT << "a"
as 0 && (cout << "a")
. The logical AND doesn't evaluate the expression on the right if the expression on the left evaluates to zero or false
; because the left-hand expression always evaluates to zero, the right-hand expression is always removed by any compiler worth using except when all optimization is disabled (and even then, obviously unreachable code may still be ignored.)
Here is an example of weird things that will break this macro:
DBOUT << "This is a debug build." << endl, doSomething();
Watch the commas. doSomething()
will always be called, regardless of whether or not _DEBUG
is defined. This is because the statement is evaluated in release builds as:
(0 && (cout << "This is a debug build." << endl)), doSomething();
// evaluates further to:
false, doSomething();
To use commas with this macro, the comma must be wrapped in parentheses, like so:
DBOUT << "Value of b: " << (a, b) << endl;
Another example:
(DBOUT << "Hello, ") << "World" << endl; // Compiler error on release build
In release builds, this is evaluated as:
(0 && (cout << "Hello, ")) << "World" << endl;
// evaluates further to:
false << "World" << endl;
which causes a compiler error because bool
cannot be shifted left by a char
pointer unless a custom operator is defined. This syntax also causes additional problems:
(DBOUT << "Result: ") << doSomething() << endl;
// evaluates to:
false << doSomething() << endl;
Just like when the comma was used poorly, doSomething()
still gets called, because its result has to be passed to the left-shift operator. (This can only occur when a custom operator is defined that left-shifts a bool
by a char
pointer; otherwise, a compiler error occurs.)
Do not parenthesize DBOUT << ...
. If you want to parenthesize a literal integer shift, then parenthesize it, but I'm not aware of a single good reason to parenthesize a stream operator.