简单的 wostream 日志记录类(带有自定义流操纵器)
我已经阅读了大量的问题、文章和文档,但我还没有找到解决我的问题的方法。
我想创建一个简单的类用于调试。最终结果将允许我做这样的事情:
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;
有了这样的想法,在记录器类中,我可以切换这些东西是否进入控制台/调试文件。
logger.setLevel(ERROR);
我已经有了一个骨架,但我无法让操作员重载以使操纵器工作。
这是 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);
};
和 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);
}
和 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;
...
这种混乱在 VS2005 中产生以下错误:
“错误 C2679:二进制 '<<' : 不 发现运算符需要一个 类型的右侧操作数 'doSetState'(或者没有 可接受的转换)”
非常感谢任何帮助。
谢谢!
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的 ostream 操作员没有正确的签名。应该是:
friend LoggerStream&运算符<< (LoggerStream&os, const doSetState&fb)
(必须使用引用,因为单遍编译器在类定义中途不知道 doSetState 的大小。)
Your ostream operator does not have the correct signature. It should be:
friend LoggerStream& operator<< (LoggerStream& os, const doSetState& fb )
(It is necessary to use a reference, because a single-pass compiler does not know the size of doSetState when it is midway through the class definition.)
问题是,当您这样做时:
它返回一个基本的 wostream 对象。因此链接它不起作用,因为没有重载:
但是您可以在单独的行上执行此操作,如下所示:
The problem is that when you do this:
It returns a basic wostream object. So chaining it doesn't work, since there is no overload for:
You can however do it on separate lines, like this:
我会采取稍微不同的方法。
我的记录器类中有一个
std::wfostream
成员,而不是从std::wostream
继承。然后,您可以拥有一个通用模板化operator<<
,它有选择地转发到嵌入流。例如:
I would go for a slightly different approach.
Instead of inheriting from
std::wostream
, I would have astd::wfostream
member in my logger class. Then you can have a generic templatedoperator<<
that selectively forwards to the embedded stream.For example: