使用预处理器取消 std::cout 代码行

发布于 2024-08-03 21:13:08 字数 179 浏览 7 评论 0原文

可以使用#define printf 删除对printf() 的所有调用。如果我有很多调试打印,例如 std::cout << x <<结束;?如何使用预处理器快速关闭单个文件中的 cout << 语句?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

阳光的暖冬 2024-08-10 21:13:08

正如“放松”已经说过的,快速解决方案是无所事事的流。不过,还有更好的实现:

class NullStream {
    public:
    NullStream() { }
    template<typename T> NullStream& operator<<(T const&) { return *this; }
};

您仍然对 std::cout 有一个小问题,因为它是三个标记的序列,并且您确实不想重新定义 std 或分别cout。一个简单的解决方案是

#ifdef NDEBUG
    #define COUT std::cout
#else
    #define COUT NullStream()
#endif

COUT << "Hello, world" << std::endl;

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;
春夜浅 2024-08-10 21:13:08

作为一般原则,应避免记录到标准输出 - 更好地记录到日志文件,然后您可以使用标准配置工具来更改日志级别,或完全关闭它。

只是我的 0.02 美元......

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

若有似无的小暗淡 2024-08-10 21:13:08

将调试输出语句替换为如下内容:

IFDBG(cout << result << endl);

然后您可以相应地定义宏:

#ifdef DEBUG
#  define IFDBG(x) x
#else
#  define IFDBG(x)
#endif

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
起风了 2024-08-10 21:13:08

定义这个宏:

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

这个宏的优点是编译器优化

如果放置在这些 IF 内的表达式在编译时是常量且可确定的,那么您几乎可以肯定编译器已将它们从代码中删除...
https://stackoverflow.com/a/14657645/5052296

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

落花随流水 2024-08-10 21:13:08

如果您正在寻找快速删除调试语句的方法,NullStream 可能是一个很好的解决方案。不过,我建议创建您自己的调试类,当需要更多调试功能时,可以根据需要扩展该类:

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
};

这是一个简单的设置,可以执行您最初想要的操作,而且它还有一个额外的好处,可以让您添加功能,例如调试级别等。

更新:
现在,由于操纵器是作为函数实现的,如果您也想接受操纵器(endl),您可以添加:

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

对于所有操纵器类型(这样您就不必重载所有操纵器类型):

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

请小心最后一个,因为它也接受常规函数指针。

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.

戏剧牡丹亭 2024-08-10 21:13:08

您可能可以进行预处理器修改,定义一个新的类似流的类,并使用名为 cerr 的实例,但它什么也不做。如果你真的很幸运,编译器会发现该函数不执行任何操作,并优化对 operator<<() 的调用。

像这样的东西

class NullStream
{
public:
  NullStream();

  NullStream& operator<<(const std::string& text) { return *this; }
  // And operators for other types, too
}
static NullStream cerr;

虽然很黑客,但最好(远)更好地浏览您的源代码并添加对日志记录的适当支持。

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.

夏の忆 2024-08-10 21:13:08

定义一个宏来替换 cout 不是您应该上传到 VCS 的东西,但如果您只是在调试期间临时执行此操作,我认为它发挥了作用。因此,您只需将 cout 替换为 ostream(0) 这样

#ifdef NDEBUG
#define cout ostream(0).flush()
#endif

,它就可以与 std::cout 和普通 cout 一起使用,并且当包含 时,ostream 可用。写入 ostream(0) 是一个空操作。完成flush函数调用,以便您获得对其的非常量引用(因此它也绑定到用于输出的非成员operator<< >std::string 等)。由于其类型为 ostream,因此它的行为应与 cout 完全相同。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文