开发者

Managing a log stream in C++ in a cout-like notation

I have a class in c++ in order to write log files for an application of mine. I have already built the class and it works, it is something like this:

class Logger {
   std::string _filename;
public: 
   void print(std::string tobeprinted);
}

Well, it is intuitive that, in order to print a line in the log file, for an object of Logger, it is simply necessary to do the following:

Logger mylogger("myfile.log");
mylogger.print(std::string("This is a log line"));

Well. Using a method approach is not the same as using a much better pattern like << is. I wo开发者_运维知识库uld like to do the following:

Logger mylogger("myfile.log");
mylogger << "This is a log line";

That's all. I suppose I must overload the << operator... But overloading using this signature (the classic one):

ostream& operator<<(ostream& output, const MyObj& o);

But I do not have a ostream... So, should I do as follows?

Logger& operator<<(Logger& output, const std::string& o);

Is this the right way? Thanks


class Log
{
public:

    enum Level { Debug, Error, Info };

    static ostream& GetStream() { return cout; }
    static bool IsLevelActive(Level l) { return true; }
};

#ifndef NO_LOG
#define LOG_ERROR(M)   do { if (Log::IsLevelActive(Log::Error))   (Log::GetStream() << "ERR: " << M << "\n"); } while (false)
#define LOG_INFO(M)    do { if (Log::IsLevelActive(Log::Info))    (Log::GetStream() << "INF: " << M << "\n"); } while (false)
#define LOG_WARNING(M) do { if (Log::IsLevelActive(Log::Warning)) (Log::GetStream() << "WRN: " << M << "\n"); } while (false)
#else
#define LOG_ERROR(M)
#define LOG_INFO(M)
#define LOG_WARNING(M)
#endif

struct MyObject {
    int a, b;
};

ostream& operator<<(ostream& ostr, const MyObject& obj) {
    ostr << "(a=" << obj.a << ", b=" << obj.b << ")";
    return ostr;
}

void test() {
    int v1 = 42;
    int v2 = 43;
    LOG_INFO("value1=" << v1 << ", value2=" << v2);

    MyObject o = {1, 2};
    LOG_INFO("obj=" << o);
}


Why not simply make Logger a sub-class of either std::ostream or std::ostringstream? Then all that functionality will already be implemented.


Yes, this is the right way. But you'll have to add << operator overloads for every data type that you need to log.


You don't really want to create whole new streams, as you then need to redefine all the stream operators. You'd only do that if you want to change entirely how data gets converted into character data. (Ick).

What I've found best for this is to create a class that will keep track of a stream and send its contents to a destination of my choice (the logger) when destructed. That, combined with a smattering of macros, gives you what you are looking for: stream syntax for logging.

Boost actually has some classes that help with this. Look at iostreams.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜