简单的wostream日志类(使用自定义流操纵器) [英] Simple wostream logging class (with custom stream manipulators)
问题描述
我一直在读大量的问题,文章和文档,但我没有找到解决我的问题。
我想创建一个用于调试的简单类。最终结果将允许我做这样的事情:
logger<错误< L这是一个问题! << endl
logger<<警告< L这可能是一个问题! << endl
logger<<信息< L这不是问题,但我认为你应该知道它< endl
有了这样的想法,在logger类中,我可以切换是否这些东西到控制台/ debug file。
logger.setLevel(ERROR);
我有一个骨架,但我不能让操作符重载操作器工作。
这里是Logger.h:
class LoggerBuffer:public wfilebuf {
//函数
public:
LoggerBuffer(){wfilebuf :: open(NUL,ios :: out); currentState = 1;}
〜LoggerBuffer(){wcout<< DELETED! << endl;}
void open(const char fname []);
void close(){wfilebuf :: close();}
virtual int sync();
void setState(int newState);
//变量
private:
int currentState;
};
class LoggerStream:public wostream {
//函数
public:
LoggerStream():wostream(new LoggerBuffer()),wios(0){}
〜LoggerStream(){delete rdbuf(); }
void open(const char fname [] = 0){
wcout< 流开放< fname<< endl;((LoggerBuffer *)rdbuf()) - > open(fname); }
void close(){((LoggerBuffer *)rdbuf()) - > close() }
void setState(int newState);
};
和Logger.cpp:
void LoggerBuffer :: open(const char fname []){
wcout< 缓冲器打开< fname<< endl
close();
wfilebuf * temp = wfilebuf :: open(fname,ios :: out);
wcout<< Temp:<温度< endl
}
int LoggerBuffer :: sync(){
wcout<< 当前状态:< currentState<< ,数据:< pbase();
return wfilebuf :: sync();
}
void LoggerBuffer :: setState(int newState){
wcout<< New buffer state =< newState<< endl
currentState = newState;
}
void LoggerStream :: setState(int newState){
wcout< New stream state =<< newState<< endl
((LoggerBuffer *)rdbuf()) - > setState(newState);
}
和main.cpp:
struct doSetState {
int _l;
doSetState(int l):_l(l){}
friend LoggerStream&运算符<< (LoggerStream& os,doSetState fb){
os.setState(3);
return(os);
}
};
...
LoggerStream test;
test.open(debug.txt);
test<< 设置状态! << doSetState(1)<< endl
...
这种混乱在VS2005中产生以下错误:
错误C2679:binary'<<':no
操作符找到一个
类型$的右手操作数b $ b'doSetState'(或没有
可接受的转换)
任何帮助是非常感谢。 p>
谢谢!
/ p>
而不是继承 std :: wostream
,我会有一个 std :: wfostream
成员在我的logger类。然后你可以有一个通用的模板运算符<<
选择性地转发到嵌入的流。
class Logger;
template< class T>记录器& operator<<(Logger& const T&);
enum LogLevel
{
debug,
info,
warning,
error
}
class Logger
{
public:
void open(const char * file){stream.open(file); }
void close(){stream.close(); }
void passLevel(Loglevel level){pass = level; }
void logLevel(LogLevel level){current = level; }
private:
bool passThrough(){return current> = pass; }
std :: wofstream stream;
LogLevel pass
LogLevel current;
friend template< class T>记录器& operator<<(Logger& const T&);
};
template< class T>
Logger& <<<(Logger& log,const T& rhs)
{
if(log.passthrough())
{
log.stream< rhs;
}
return log;
}
Logger& operator<<<(Logger& LogLevel level)
{
log.logLevel(level);
return log;
}
struct setLogLevel {
setLogLevel(LogLevel l):level(l){}
LogLevel level;
};
Logger& operator<<<(Logger& const setLogLevel setter)
{
log.passLevel(setter.level);
return log;
}
I've been reading tons of questions, articles, and documentation, but I've not found a solution to my problem.
I'd like to create a simple class for use in debugging. The end result of which would allow me to do something like this:
logger << error << L"This is a problem!" << endl;
logger << warning << L"This might be a problem!" << endl;
logger << info << L"This isn't a problem but I thought you should know about it" << endl;
With the idea that within the logger class I can toggle whether or not these things make it to the console/debug file.
logger.setLevel(ERROR);
I've got a skeleton together but I can't get the operator overloading for the manipulators to work.
Here's Logger.h:
class LoggerBuffer : public wfilebuf {
// Functions
public:
LoggerBuffer() { wfilebuf::open("NUL", ios::out); currentState = 1;}
~LoggerBuffer() {wcout << "DELETED!" << endl;}
void open(const char fname[]);
void close() {wfilebuf::close();}
virtual int sync();
void setState(int newState);
// Variables
private:
int currentState;
};
class LoggerStream : public wostream {
// Functions
public:
LoggerStream() : wostream(new LoggerBuffer()), wios(0) {}
~LoggerStream() { delete rdbuf(); }
void open(const char fname[] = 0) {
wcout << "Stream Opening " << fname << endl;((LoggerBuffer*)rdbuf())->open(fname); }
void close() { ((LoggerBuffer*)rdbuf())->close(); }
void setState(int newState);
};
And Logger.cpp:
void LoggerBuffer::open(const char fname[]) {
wcout << "Buffer Opening " << fname << endl;
close();
wfilebuf* temp = wfilebuf::open(fname, ios::out);
wcout << "Temp: " << temp << endl;
}
int LoggerBuffer::sync() {
wcout << "Current State: " << currentState << ", Data: " << pbase();
return wfilebuf::sync();
}
void LoggerBuffer::setState(int newState) {
wcout << "New buffer state = " << newState << endl;
currentState = newState;
}
void LoggerStream::setState(int newState) {
wcout << "New stream state = " << newState << endl;
((LoggerBuffer*)rdbuf())->setState(newState);
}
And main.cpp:
struct doSetState {
int _l;
doSetState ( int l ): _l ( l ) {}
friend LoggerStream& operator<< (LoggerStream& os, doSetState fb ) {
os.setState(3);
return (os);
}
};
...
LoggerStream test;
test.open("debug.txt");
test << "Setting state!" << doSetState(1) << endl;
...
This mess produces the following error in VS2005:
"error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'doSetState' (or there is no acceptable conversion)"
Any help is GREATLY appreciated.
Thanks!
I would go for a slightly different approach.
Instead of inheriting from std::wostream
, I would have a std::wfostream
member in my logger class. Then you can have a generic templated operator<<
that selectively forwards to the embedded stream.
For example:
class Logger;
template<class T> Logger& operator<<(Logger&, const T&);
enum LogLevel
{
debug,
info,
warning,
error
};
class Logger
{
public:
void open(const char* file) { stream.open(file); }
void close() { stream.close(); }
void passLevel(Loglevel level) { pass = level; }
void logLevel(LogLevel level) { current = level; }
private:
bool passThrough() { return current >= pass; }
std::wofstream stream;
LogLevel pass;
LogLevel current;
friend template<class T> Logger& operator<<(Logger&, const T&);
};
template<class T>
Logger& operator<<(Logger& log, const T& rhs)
{
if (log.passthrough())
{
log.stream << rhs;
}
return log;
}
Logger& operator<<(Logger&, LogLevel level)
{
log.logLevel(level);
return log;
}
struct setLogLevel {
setLogLevel(LogLevel l) : level(l) { }
LogLevel level;
};
Logger& operator<<(Logger&, const setLogLevel setter)
{
log.passLevel(setter.level);
return log;
}
这篇关于简单的wostream日志类(使用自定义流操纵器)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!