有没有办法创建一个基本上什么都不做的ostream实例?
例如:
std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
我可以创建一个ostringstream,但数据将被缓冲(我真的不想用它们做任何事情,所以它增加了无用的开销)。
有什么想法吗?
[edit] 找到符合我需求的related question。但是,我认为如何使用标准c ++创建一个有效(无badbit)输出流的答案会很有用。
答案 0 :(得分:58)
您需要自定义streambuf。
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
是缓冲区必须将数据输出到流的实际目标时调用的函数。 1}}类在调用溢出时不执行任何操作,因此使用它的任何流都不会产生任何输出。
答案 1 :(得分:28)
如果这是为了禁用日志输出,那么dummyStream
仍然会导致参数被评估。如果要在禁用日志记录时将影响降至最低,则可以依赖条件,例如:
#define debugStream \
if (debug_disabled) {} \
else std::cerr
所以如果您有以下代码:
debugStream << "debugging output: " << foo() << std::endl;
如果debug_disabled
为真,则不会评估任何参数。
答案 2 :(得分:3)
新流类的基本方法是:
std::streambuf
; std::ostream
派遣一名成员,即您的streambuf班。希望这会给你一些指示;对不起,我没有时间将其扩展为完整答案。
更新:有关详细信息,请参阅john's answer。
答案 3 :(得分:0)
如果您担心调试器的开销,则可以编写一个非常简单的代码以使编译时的调试消息无效。这就是我在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 (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宏或您选择检查的任何宏即可。
现在您的代码将由编译器进行优化,因为当任何东西都作废时,它(大部分时间)将不包含在生成的二进制文件中,从而使二进制文件生产就绪。
答案 4 :(得分:0)
对于运行时可控制的日志消息重定向,这是一个结合了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
。
答案 5 :(得分:-1)
我需要一个类型为ostream的空流,所以我做了类似的事情:
struct NullStream: public stringstream {
NullStream(): stringstream() {}
};
template<typename T>
void operator<<(const NullStream&, const T&) {}
申请代码:
NullStream ns;
ostream &os = ns;
os << "foo";
真正的问题是我继承的所有公共方法,但我并不关心所以我只是没有打扰它们。