C++ 标准无操作输出流
有没有办法创建一个基本上什么都不做的ostream实例 例如:C++ 标准无操作输出流,c++,iostream,C++,Iostream,有没有办法创建一个基本上什么都不做的ostream实例 例如: std::ostream dummyStream(...); dummyStream << "Nothing will be printed"; std::ostream dummyStream(…); dummyStream您需要自定义streambuf class NullBuffer : public std::streambuf { public: int overflow(int c) { return
std::ostream dummyStream(...);
dummyStream << "Nothing will be printed";
std::ostream dummyStream(…);
dummyStream您需要自定义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";
null缓冲区null\u缓冲区;
std::ostream空\u流(&null\u缓冲区);
null_stream如果这是为了禁用日志输出,则您的dummyStream
仍将导致对参数求值。如果要在禁用日志记录时将影响降至最低,可以依赖条件,例如:
#define debugStream \
if (debug_disabled) {} \
else std::cerr
因此,如果您有如下代码:
debugStream << "debugging output: " << foo() << std::endl;
debugStream创建新流类的基本方法是:
从std::streambuf
派生一个类李>
重写该类中的虚拟函数。这是真正的工作要做的地方。在您的情况下,空实现应该足够好了
从std::ostream
派生一个包含一个成员的类,即streambuf类
streamclass的构造函数应该将指向该成员的指针转发到std::ostream的基构造函数
不过,恐怕您无法摆脱格式化步骤
希望这能给你一些建议;对不起,我没有时间把这个问题扩展成一个完整的答案
更新:有关详细信息,请参阅。我需要一个类型为ostream的空流,因此我执行了如下操作:
struct NullStream: public stringstream {
NullStream(): stringstream() {}
};
template<typename T>
void operator<<(const NullStream&, const T&) {}
struct NullStream:public stringstream{
NullStream():stringstream(){}
};
模板
void操作符如果您担心调试器的开销,那么您可以编写一个非常简单的代码,在编译时消除调试消息。这是我用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;
}
#包括
#定义调试//是否在config.h中定义调试。
#ifdef调试
/*
*用流替换std::cout,您不需要
*担心上下文,因为宏只是搜索
*并在编译时替换。
*/
#为日志消息的运行时可控重定向定义LOG_START std::cout,这是一个结合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
类调试流{
私人:
类NullStream:public std::ostream{
私人:
类NullBuffer:public std::streambuf{
公众:
int溢出(int c)重写{return c;}
}缓冲区;
公众:
NullStream():std::ostream(&缓冲区{}
}空值(0);;
std::ostream&output;
bool-enabled;
公众:
DebugStream(std::ostream&output=std::cout):输出(output),已启用(false){
void enable(const bool enable){enabled_u=enable;}
模板std::ostream&operatorI被指向。Boost.Iostreams
是选项吗?可以创建一个方便的类类NullStream:public std::ostream{public:NullStream():std::ostream(&m_sb){}private:NullBuffer m_sb;};
,这将用法简化为NullStream null\u stream;null\u stream这太棒了,我建议添加@Sjoerd的建议。我实现了一些与他的建议完全相同的东西,直到我回到upvote时才看到他的评论。只是一个问题:函数可能会导致失败,将流变成失败状态(不过,大多数人不会在意)。为了避免这种情况,您需要返回not_eof()的结果。此外,缓冲字符比在假定不太可能的路径上调用
virtual`函数更有效,也就是说,我还建议添加一个被忽略的缓冲区。覆盖将变成int溢出(intc){返回this->setp(std::begin(d_buffer),std::end(this->d_buffer);std::char_traits::not_eof(c);}
。同样,覆盖xsputn()也是合理的
什么也不做。@DietmarKühl:你介意将其编辑到答案中,还是写下你自己的答案?我很抱歉回答了这个问题,但我真的需要知道:这个答案在性能方面是否比选择的答案更好?如果debug_disabled是一个常量(或者更合适的宏),编译器可能(会?)优化else子句,而使用nullbuffer仍然会导致流输入被处理,只会被放入一个空设备。这是真的吗?还是假的?如果有人能帮我解释一下,那就太棒了。@bobismijnnaam:事实上,在我发布它的那天晚些时候,有人在一个问题中剽窃了这个答案:-).Hmm,不管怎样,我还是同意你的答案。整个NullStream的工作似乎太多了。这是一个很好的解决方案,但是有没有可能在不包含iostream
或定义一次性全局变量的情况下做类似的事情?@Paul:问题是关于使用ostream
,我只是选择了一个已经读过的y可用。若要禁用日志记录,日志行必须位于else
侧。因此,如果目标是始终禁用,只需使用true
而不是变量。编译器不会优化out函数调用。您需要将log_START定义为if(0){(void)
,而log_END定义为}
。即使禁用了优化功能,也会对其进行优化-至少gcc在使用-O0编译时能够这样做。@DanielFrużyński感谢您的提示。我已经做了更改。
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);