One can remove all calls to printf()
using #define printf
. What if I have a lot of debug prints like std::cout << x << endl;
? How can I quickly switch off cout <<
statements in a single file using preprocessor?
views:
338answers:
6Substitute your debug output statements with something like this:
IFDBG(cout << result << endl);
Then you can define macros accordingly:
#ifdef DEBUG
# define IFDBG(x) x
#else
# define IFDBG(x)
#endif
You can probably do a preprocessor hack that defines a new stream-like class, with an instance named cerr
, that just does nothing. If you're really lucky, the compiler will see that the function does nothing, and optimize the calls to operator<<()
out.
Something like
class NullStream
{
public:
NullStream();
NullStream& operator<<(const std::string& text) { return *this; }
// And operators for other types, too
}
static NullStream cerr;
This is quite the hack though, it's (far) better to go through your source and add proper support for logging.
As a general principle logging to stdout should be avoided - far better to log to a logfile, and then you can use standard configuration tools to change log levels, or turn it off altogether.
Just my $0.02.....
As "unwind" already said, the quick solution is a do-nothing stream. There are better implementations though:
class NullStream {
public:
NullStream() { }
template<typename T> NullStream& operator<<(T const&) { return *this; }
};
You still have a slight issue with std::cout
since that's a sequence of three tokens, and you really don't want to redefine std
or cout
individually. A simple solution is
#ifdef NDEBUG
#define COUT std::cout
#else
#define COUT NullStream()
#endif
COUT << "Hello, world" << std::endl;
NullStream can be a good solution if you are looking for something quick that removes debug statements. However I would recommend creating your own class for debugging, that can be expanded as needed when more debug functionality is required:
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
};
This is a simple setup that can do what you want initially, plus it has the added benefit of letting you add functionality such as debug levels etc..
You may just replace cout
by ostream(0)
like
#ifdef NDEBUG
#define cout ostream(0).flush()
#endif
This way, it works with both std::cout
and plain cout
, and ostream
is available when including <iostream>
. Writing into a ostream(0)
is a no-op. The flush
function call is done so that you get a non-const reference to it (so it also binds to non-member operator<<
that's used for outputting std::string
and others). As its type is ostream
, it should behave exactly like cout
.