4

我有一些代码中散布着这样的结构

if(debug) {
    Output << "f1: " << f1() << "\n";
}

现在我想做的是写一个流类Debug,我可以这样写

Debug << "f1: " << f1() << "\n";

如果设置了一些全局标志,那么这将生成输出,否则不会。

现在:这可以很容易地通过Debug返回一个流去/dev/null吞掉输出来完成。问题是f1()仍然会被评估(并“渲染”成可能更昂贵的文本表示),这可能对性能非常不利。

现在我的问题是:是否有任何技巧可以跳过

"f1: " << f1() << "\n"

完全如果Debug决定不应该做任何输出?类似于 C++ 为f() && g()whereg()不评估 if f()is的短路false(我认真考虑编写一个用作输出运算符的流类,&&但从我读到的内容来看,短路不是为重载而做的operator&&

4

3 回答 3

5

你可以做的是定义这个宏:

#define Debug_Stream \
if(!debug); else Output

这将使:

Debug_Stream << "f1: " << f1() << "\n";

变得等价于:

if(debug) {
    Output << "f1: " << f1() << "\n";
}

但从字面上看(加上空格以提高可读性)

if(!debug);
else
    Output << "f1: " << f1() << "\n";
于 2012-08-06T17:36:16.183 回答
4

如果您不反对宏,并且愿意接受以下语法:

Debug( "f1: " << f() << '\n' );

这很简单:只需定义如下内容:

#define Debug( x ) debug != NULL && *debug << x;

然而,这有点危险,因为您不能采取通常的预防措施,将论点放在括号中。(另一方面,我已经看到它在许多应用程序中使用,没有问题。)宏方法具有额外的优势,允许您根据 __FILE__需要__LINE__自动插入。或者通过将宏定义为空,有条件地完全抑制所有代码。

于 2012-08-06T17:35:53.753 回答
2

我认为您可以通过创建一个包装昂贵的函数调用的延迟评估器来做到这一点。您的流会知道它需要调用引用函数的延迟评估器类型,否则它不会对其进行操作,从而防止昂贵的调用。no-debug 流知道,对于您的代理评估器对象,只需完全跳过评估。

例如,调用可能如下所示:

Debug << "123" << delay(f()) << "456" << std::endl;

这确实涉及记住在调试行中调用延迟。它确实避免了对宏的需要,这在您的情况下可能是也可能不是关键问题。

于 2012-08-06T17:41:35.187 回答