gpt4 book ai didi

c++ - 我可以使用流运算符重写日志记录宏以使用 C++ 模板函数吗?

转载 作者:可可西里 更新时间:2023-11-01 18:20:58 32 4
gpt4 key购买 nike

我们的项目使用一个宏来使单行语句中的日志记录变得简单易行,如下所示:

DEBUG_LOG(TRACE_LOG_LEVEL, "The X value = " << x << ", pointer = " << *x);

宏将第二个参数转换为字符串流参数,并将其发送到常规 C++ 记录器。这在实践中非常有效,因为它使多参数日志记录语句非常简洁。然而,Scott Meyers 在 Effective C++ 3rd Edition 中表示,“通过使用内联函数模板,您可以获得宏的所有效率以及常规函数的所有可预测行为和类型安全性”(第 2 项)。我知道在 C++ 中使用宏有很多与可预测行为相关的问题,所以我试图在我们的代码库中消除尽可能多的宏。

我的日志宏定义类似于:

#define DEBUG_LOG(aLogLevel, aWhat) {  \
if (isEnabled(aLogLevel)) { \
std::stringstream outStr; \
outStr<< __FILE__ << "(" << __LINE__ << ") [" << getpid() << "] : " << aWhat; \
logger::log(aLogLevel, outStr.str()); \
}

我已经多次尝试将其重写为不使用宏的内容,包括:

inline void DEBUG_LOG(LogLevel aLogLevel, const std::stringstream& aWhat) {
...
}

还有……

template<typename WhatT> inline void DEBUG_LOG(LogLevel aLogLevel, WhatT aWhat) {
... }

无济于事(以上 2 次重写都不会针对第一个示例中的日志代码进行编译)。还有其他想法吗?这可以做到吗?还是最好将其保留为宏?

最佳答案

日志记录仍然是您无法完全取消宏的少数几个地方之一,因为您需要调用站点信息( __LINE____FILE__ ……),而这些信息在其他情况下是不可用的。另见 this question .

但是,您可以将日志记录逻辑移动到单独的函数(或对象)中,并通过宏仅提供调用站点信息。为此,您甚至不需要模板函数。

#define DEBUG_LOG(Level, What) \
isEnabled(Level) && scoped_logger(Level, __FILE__, __LINE__).stream() << What

有了这个,用法保持不变,这可能是个好主意,这样您就不必更改大量代码。随着&& ,您会得到与 if 相同的短路行为条款。

现在,scoped_logger将是一个 RAII 对象,它实际上会记录它在被销毁时所获得的内容,也就是在析构函数中。

struct scoped_logger
{
scoped_logger(LogLevel level, char const* file, unsigned line)
: _level(level)
{ _ss << file << "(" << line << ") [" << getpid() << "] : "; }

std::stringstream& stream(){ return _ss; }
~scoped_logger(){ logger::log(_level, _ss.str()); }
private:
std::stringstream _ss;
LogLevel _level;
};

公开底层std::stringstream object 省去了我们自己编写 operator<< 的麻烦重载(这很愚蠢)。通过函数实际公开它的需要很重要;如果scoped_logger对象是临时的(右值),std::stringstream 也是。 operator<< 的成员和唯一成员重载如果我们不以某种方式将其转换为左值(引用),将会被发现。您可以阅读有关此问题的更多信息 here (请注意,此问题已在 C++11 中使用右值流插入器修复)。这种“转换”是通过调用成员函数来完成的,该成员函数只返回对流的正常引用。

Small live example on Ideone.

关于c++ - 我可以使用流运算符重写日志记录宏以使用 C++ 模板函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9667963/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com