jcs*_*jcs 32 c++ debugging logging
我正在寻找一个日志类,其中包含Info,Error等成员,可以配置输出到控制台,文件或无处.
为了提高效率,我希望避免格式化将要丢弃的消息的开销(即,不以详细模式运行时的信息消息).如果我实现一个输出到无处的自定义std :: streambuf,我想std :: ostream层仍将执行所有格式化.任何人都可以建议一种方法来拥有一个真正的"空"std :: ostream,它可以避免在传递给它的参数上做任何工作<<
吗?
谢谢.
小智 16
一个快速的谷歌想出了这个可能有用的例子.除了编译和运行之外,我不提供任何保证:-)
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
int main() {
onullstream os;
os << 666;
}
Run Code Online (Sandbox Code Playgroud)
oll*_*g23 13
所有,感谢分享代码,我只是做一个测试,然后Neil的方法仍然会进行字符串格式化,例如:
#include <streambuf>
#include <ostream>
#include <iostream>
using namespace std;
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
class MyClass
{
int a;
friend ostream& operator<< (ostream&, MyClass const&);
};
ostream& operator<<(ostream& out,MyClass const& b)
{
std::cout<<"call format function!!";
out << b.a;
return out;
}
int main() {
onullstream os;
MyClass obj;
os<<obj;
}
Run Code Online (Sandbox Code Playgroud)
运行这个程序,你会发现"ostream&operator <<(ostream&out,MyClass const&b)"将被调用.因此,仍然会调用obj上的格式.因此,我们仍然无法避免格式化消息的开销.
小智 4
为了防止operator<<()
调用进行格式化,您应该在编译时知道流类型。这可以通过宏或模板来完成。
我的模板解决方案如下。
class NullStream {
public:
void setFile() { /* no-op */ }
template<typename TPrintable>
NullStream& operator<<(TPrintable const&)
{ return *this; } /* no-op */
}
template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
TErrorStream& errorStream() {
return m_errorStream;
}
private:
TErrorStream m_errorStream;
};
//usage
int main() {
Logger<std::ofstream> normal_logger; // does real output
normal_logger.errorStream().open("out.txt");
normal_logger.errorStream() << "My age is " << 19;
Logger<NullStream> null_logger; // does zero output with zero overhead
null_logger.errorStream().open("out.txt"); // no-op
null_logger.errorStream() << "My age is " << 19; // no-op
}
Run Code Online (Sandbox Code Playgroud)
由于必须在编译时执行此操作,因此它当然非常不灵活。
例如,您无法在运行时从配置文件决定日志记录级别。