标签:流式 hat util c++ 代码 ESS long __line__ mit
在 Qt的源码与Protobuf 的代码中,看到相同的简单消息(日志)输出的类实现,基本思路是使用宏定义,重载临时类对象,调用类方法或者通过析构函数自动调用输出方法,实现消息输出。这里以 Protobuf 的LogMessage 类为例,简单描述实现方法。
类定义很简单,主要是构造函数、重载的 operator<< 操作符、Finish方法。构造函数传入日志等级、文件名及行号,为输出用。重载的 << 操作符为了流式输出。在后边实现了个私有的 Finish 方法,该方法简单粗暴,就是调用输出函数,如果是 Fatal 等级输出,还会抛出异常或者 abort。其定义如下:
enum LogLevel { LOGLEVEL_INFO, // Informational. This is never actually used by // libprotobuf. LOGLEVEL_WARNING, // Warns about issues that, although not technically a // problem now, could cause problems in the future. For // example, a // warning will be printed when parsing a // message that is near the message size limit. LOGLEVEL_ERROR, // An error occurred which should never happen during // normal use. LOGLEVEL_FATAL, // An error occurred from which the library cannot // recover. This usually indicates a programming error // in the code which calls the library, especially when // compiled in debug mode. }; class LIBPROTOBUF_EXPORT LogMessage { public: LogMessage(LogLevel level, const char* filename, int line); ~LogMessage(); LogMessage& operator<<(const std::string& value); LogMessage& operator<<(const char* value); LogMessage& operator<<(char value); LogMessage& operator<<(int value); LogMessage& operator<<(uint value); LogMessage& operator<<(long value); LogMessage& operator<<(unsigned long value); LogMessage& operator<<(long long value); LogMessage& operator<<(unsigned long long value); LogMessage& operator<<(double value); LogMessage& operator<<(void* value); LogMessage& operator<<(const StringPiece& value); LogMessage& operator<<(const ::google::protobuf::util::Status& status); LogMessage& operator<<(const uint128& value); private: friend class LogFinisher; void Finish(); LogLevel level_; const char* filename_; int line_; std::string message_; };
同时实现了一个 LogFinisher 类,只重载了 operator= 操作符,该方法只是调用 LogMessage 的 Finish 方法。
1 class LIBPROTOBUF_EXPORT LogFinisher { 2 public: 3 void operator=(LogMessage& other) { 4 other.Finish(); 5 } 6 };
再者实现方便使用的宏定义,定义如下所示。主要为 GOOGLE_LOG 宏,该宏构造 LogMessage 临时对象,调用 LogFinisher 的 operator= 方法,实现消息输出。在Qt 的代码中,并没有实现类似 LogFinisher 的类,直接构造了MessageLog 临时对象,在对象析构时调用输出函数,临时对象生命周期会在构造完执行析构,执行消息输出。以下宏定义中还定义了 GOOGLE_LOG_IF ,即条件为 true 时,什么都不做 (void)0,为 false时调用 GOOGLE_LOG。
1 #define GOOGLE_LOG(LEVEL) 2 ::google::protobuf::internal::LogFinisher() = 3 ::google::protobuf::internal::LogMessage( 4 ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) 5 #define GOOGLE_LOG_IF(LEVEL, CONDITION) 6 !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) 7 8 #define GOOGLE_CHECK(EXPRESSION) 9 GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " 10 #define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) 11 #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) 12 #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) 13 #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) 14 #define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) 15 #define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) 16 #define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B))
通过以上实现,则可以在代码中使用以下形式进行消息输出或者断言。第一行直接输出 "Hello sunshy",额,sunshy 是寡人姓名拼音的简拼,第二行在var0 和 var1 不相等时输出后边的消息,同时抛异常或者abort,相等时则 do nothing
1 GOOGLE_LOG(INFO)<< "Hello " <<"sunshy\n"; 2 GOOGLE_CHECK_EQ(var0, var1)<<" var0 not equal var\n";
最新工作的事心有不畅,随便写写,以遣胸怀
C++ Simple Message/Logging Class
标签:流式 hat util c++ 代码 ESS long __line__ mit
原文地址:https://www.cnblogs.com/sun-shy/p/9833791.html