我正在尝试实现自己的QDebug()样式调试输出流,这基本上是我到目前为止所做的:
struct debug
{
#if defined(DEBUG)
template<typename T>
std::ostream& operator<<(T const& a) const
{
std::cout << a;
return std::cout;
}
#else
template<typename T>
debug const& operator<<(T const&) const
{
return *this;
}
/* must handle manipulators (endl) separately:
* manipulators are functions that take a stream& as argument and return a
* stream&
*/
debug const& operator<<(std::ostream& (*manip)(std::ostream&)) const
{
// do nothing with the manipulator
return *this;
}
#endif
};
典型用法:
debug() << "stuff" << "more stuff" << std::endl;
但我不想添加std :: endl;
我的问题基本上是,如何判断运算符的返回类型&lt;&lt;不会被另一个运营商使用&lt;&lt; (等附加endl)?
我能想到实现这样的任何事情的唯一方法是创建一个要打印的事物列表,与debug()创建的每个临时对象相关联,然后打印所有内容,以及尾随换行符(我可以在~debug()中做一些巧妙的事情,比如插入空格),但显然这并不理想,因为我没有保证临时对象会在范围结束之前销毁(或者我?)。 / p>
答案 0 :(得分:17)
这样的事情会:
struct debug {
debug() {
}
~debug() {
std::cerr << m_SS.str() << std::endl;
}
public:
// accepts just about anything
template<class T>
debug &operator<<(const T &x) {
m_SS << x;
return *this;
}
private:
std::ostringstream m_SS;
};
哪个可以让你做这样的事情:
debug() << "hello world";
我使用了这样的模式与一个锁相结合来提供像日志系统一样的流,它可以保证日志条目以原子方式写入。
注意:未经测试的代码,但应该有效: - )
答案 1 :(得分:9)
Qt使用类似于@Evan的方法。有关实现的详细信息,请参阅a version of qdebug.h,但它们将所有内容流式传输到基础文本流,然后在销毁qDebug()返回的临时QDebug对象时刷新流和结束行。
答案 2 :(得分:5)
当你写这是典型用法时:
debug() << "stuff" << "more stuff" << std::endl;
你是否打算每次使用它时构建一个调试对象?如果是这样,您应该能够通过调试析构函数添加换行符来获得所需的行为:
~debug()
{
*this << std::endl;
... the rest of your destructor ...
}
这意味着你不能做这样的事情:
// this won't output "line1" and "line2" on separate lines
debug d;
d << "line1";
d << "line2";
答案 3 :(得分:0)
流插入(<<
)和提取(>>
)应该是非成员。
我的问题基本上是,我怎么能 告诉何时返回类型 运营商LT;&LT;是不会被使用 另一个运算符&lt;&lt; (等等附加 ENDL)?
你做不到。创建一个成员函数以专门附加此函数,或者在完成这些链接调用后附加endl
。记录您的课程,以便客户知道如何使用它。那是你最好的选择。