1

我有一个Logger带有公共方法的静态 C++ 类:

static std::ostringstream& Log(int sev);

如您所见,该方法评估为 ostringstream,因此我只需键入以下内容即可记录我的内容:

Logger::log(MY_SEVERITY) << "hello world";

由于编译器首先评估 log(MY_SEVERITY),然后评估整个表达式,我需要第二种方法:

static FVResult_t Flush();

将 ostringstream 的内容实际写入磁盘。Flush() 必须在任何 Log() 调用之前调用,所以每当我想记录一些东西时,我必须依次调用这两种方法:

Logger::log(MY_SEVERITY) << "hello world";
Logger::Flush();

到目前为止,一切都很好。

现在我的问题是,我想编写一个 C++ 宏,它结合了两种方法,让我可以做这样的事情:

LOGMACRO(MY_SEVERITY) << "hello world";

我试过:

#define LOGMACRO(lev) \
Logger::Log(lev) \
Logger::Flush();

然而,正如我所料,C++ 编译器抱怨缺少 ostringstream。如何仅在我的宏中将此类 ostringstream 传递给 Logger::Log(lev)?

4

3 回答 3

3

您只能使用以下宏

#define LOGMACRO(lev, msg) \
Logger::Log(lev) << msg; \
Logger::Flush();

使用喜欢

LOGMACRO(MY_SEVERITY, "hello world")

但是,我认为,那个功能,或者手动使用std::endl,或者使用自己的机械手会更好。

功能可以是这样的

inline void log(int severity, const std::string& msg)
{
   Logger::Log(severity) << msg;
   Logger::Flush();
}

接着

log(MY_SEVERITY, "Hello!");
于 2013-04-12T08:23:08.373 回答
1

您的问题是宏在“Hello world”流式传输到您的记录器之前正在扩展,导致以下结果:

Logger::Log(MY_SEVERITY)
Logger::flush();
<< "hello world"

这不是有效的 C++。

最好的方法是使用宏,例如:

#define LOG_ERROR( msg ) \
do { \
    std::ostringstream oss; \
    oss << __func__ << "() ERROR: " << msg; \
    Logger::Log( LEVEL_ERROR ) << oss.str(); \
    Logger::Flush(); \
} while(0)

该宏可以按如下方式使用:

void foo()
{
    /// stuff that detects a error
    LOG_ERROR( "Parameter X has an invalid value " << std::hex << x 
               << " should be in the range " << y " - " z" );
}

这将输出一些类似的东西

foo() : Parameter X has an invalid value F7  should be in the range 0 - F0

这种机制还意味着您不必担心重置流输出说明符,例如std::hex在宏的调用点处LOG_ERROR

或者,它可能值得调查boost::log

于 2013-04-12T08:39:00.907 回答
0

有一个更简单的非宏观解决方案。让我们Logger::log成为一个类,有一个Logger::log::log(int)构造函数。Logger::log(MY_SEVERITY)现在是一个临时的,它一直存在到Logger::log(MY_SEVERITY) << "hello world";语句的末尾。

现在定义Logger::log::~log并让它调用Logger::Flush().

于 2013-09-25T13:31:35.720 回答