Cancelling std::cout code lines using preprocessor

情到浓时终转凉″ 提交于 2019-12-06 05:34:01

问题


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?


回答1:


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

Update: Now since manipulators are implemented as functions, if you want to accept manipulators as well (endl) you can add:

MyDebug & operator<<(std::ostream & (*pf)(std::ostream&))
{
  stream << pf;
  return *this;
}

And for all manipulator types (So that you don't have to overload for all manipulator types):

template<typename R, typename P>
MyDebug & operator<<(R & (*pf)(P &))
{
  stream << pf;
  return *this;
}

Be careful with this last one, because that will also accept regular functions pointers.




回答2:


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;



回答3:


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




回答4:


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



回答5:


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.




回答6:


Define this macro :

#ifdef DEBUG
    #define MY_LOG std::cout
#else
    #define MY_LOG if(false) std::cout
#endif

This macro advantage is in compiler optimization

If expressions placed inside those IFs are constant and determinable at the time of compilation, then you may be almost sure that the compiler has already removed them off the code for you... https://stackoverflow.com/a/14657645/5052296




回答7:


Defining a macro that replaces cout is not something you should upload to your VCS, but if you just do it temporarily during debugging, I think it serves its place. So you can 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.



来源:https://stackoverflow.com/questions/1389538/cancelling-stdcout-code-lines-using-preprocessor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!