有没有办法创建一个基本上不做任何事情的 ostream 实例?
例如 :
std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
我可以只创建一个 ostringstream,但数据将被缓冲(我真的不想用它们做任何事情,所以它增加了无用的开销)。
任何想法 ?
[编辑]找到适合我需要的相关问题。但是,我认为有一个答案来说明如何使用标准 c++ 创建一个有效的(无坏位)输出流可能会很有用。
您需要一个自定义的流缓冲区。
class NullBuffer : public std::streambuf
{
public:
int overflow(int c) { return c; }
};
然后,您可以在任何 ostream 类中使用此缓冲区
NullBuffer null_buffer;
std::ostream null_stream(&null_buffer);
null_stream << "Nothing will be printed";
streambuf::overflow
是当缓冲区必须将数据输出到流的实际目的地时调用的函数。上面的NullBuffer
类在调用溢出时什么都不做,所以任何使用它的流都不会产生任何输出。
如果这是为了禁用日志输出,您dummyStream
仍然会导致评估参数。如果您想在禁用日志记录时最小化影响,您可以依赖条件,例如:
#define debugStream \
if (debug_disabled) {} \
else std::cerr
因此,如果您有如下代码:
debugStream << "debugging output: " << foo() << std::endl;
debug_disabled
如果为真,则不会评估任何参数。
新流类的基本方法是:
std::streambuf
从;派生一个类std::ostream
,即您的 streambuf 类。不过,恐怕您不会摆脱格式化步骤。
希望这能给您一些指示;抱歉,我没有时间将其扩展为完整的答案。
更新:有关详细信息,请参阅约翰的答案。
对于日志消息的运行时可控重定向,结合了 john 和 Sjoerd 思想的自包含解决方案:
class DebugStream {
private:
class NullStream : public std::ostream {
private:
class NullBuffer : public std::streambuf {
public:
int overflow(int c) override { return c; }
} buffer_;
public:
NullStream() : std::ostream(&buffer_) {}
} null_;
std::ostream &output_;
bool enabled_;
public:
DebugStream(std::ostream &output = std::cout) : output_(output), enabled_(false) {}
void enable(const bool enable) { enabled_ = enable; }
template <typename T> std::ostream& operator<<(const T &arg) {
if (enabled_) return output_ << arg;
else return null_ << arg;
}
};
extern DebugStream debug_stream;
#define TRACE_ENABLE(x) debug_stream.enable(x)
#define TRACELN(x) debug_stream << x << std::endl
#define TRACE(x) debug_stream << x
然后你可以做类似的事情:
TRACELN("The value of x is " << x " and the value of y is " << y);
#define
使用跟踪宏将跟踪语句完全从发布版本中删除到空语句也很容易。
不过,您仍然需要在debug_stream
某个全局位置定义。
如果您担心调试器的开销,那么您可以编写一个非常简单的代码来取消编译时的调试消息。这就是我用于我的 c++ 程序的内容。
#include <iostream>
#define DEBUGGING // Define this in your config.h or not.
#ifdef DEBUGGING
/*
* replace std::cout with your stream , you don't need to
* worry about the context since macros are simply search
* and replace on compilation.
*/
#define LOG_START std::cout <<
#define LOG_REDIR <<
#define LOG_END << std::endl;
#else
#define LOG_START if(0){(void)
#define LOG_REDIR ;(void)
#define LOG_END ;}
#endif // DEBUGGING
int main(){
LOG_START "This is a log message " LOG_REDIR "Still a log message." LOG_END;
return 0;
}
现在在制作项目时,检查用户是否要禁用日志记录,如果是,只需取消定义 DEBUGGING 宏或您选择检查的任何宏。
现在您的代码将由编译器优化,因为当任何内容无效时,它不会包含在生成的二进制文件中(大部分时间),从而使二进制文件准备就绪。
我需要一个 ostream 类型的空流,所以我做了这样的事情:
struct NullStream: public stringstream {
NullStream(): stringstream() {}
};
template<typename T>
void operator<<(const NullStream&, const T&) {}
申请代码:
NullStream ns;
ostream &os = ns;
os << "foo";
真正的问题是我继承但不关心的所有公共方法,所以我只是懒得重写它们。