views:

338

answers:

6

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?

+2  A: 

Substitute 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
Ferdinand Beyer
That doesn't look like it will work with `IFDBG(cout << foo(x,y) << std::endl);`. The comma is going to break the macro.
MSalters
No, that won't break the macro, since macros can escape scope whithin parenthesis. However this call will break it: IFDBG(cout << foo<int, float>() << std::endl);
Ramon Zarazua
+3  A: 

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.

unwind
+5  A: 

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.....

Visage
+8  A: 

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;
MSalters
+1  A: 

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..

Ramon Zarazua
A: 

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.

Johannes Schaub - litb