__函数和日志记录 我在C++中实现了一个日志处理程序,它工作得很好,所有的东西都有,但是有一件事我可以找到,那就是记录器得到的输出。

__函数和日志记录 我在C++中实现了一个日志处理程序,它工作得很好,所有的东西都有,但是有一件事我可以找到,那就是记录器得到的输出。,c++,logging,callstack,func,C++,Logging,Callstack,Func,我想这并不是什么大问题,但我偶然发现了\uuu func\uuu标识符,它基本上会保留当前函数的函数名 因此,我的日志类中有一个名为Write的静态函数,它采用日志级别和变量列表。因此,我将其称为: Log::Write(LOG_DEBUG, "this is an integer: %d", 10); 它将打印: 2013-01-02 => 10:12:01.366 [DEBUG]: this is an integer: 10 然而,我认为在消息中也包含调用者可能是有用的,以产生如

我想这并不是什么大问题,但我偶然发现了
\uuu func\uuu
标识符,它基本上会保留当前函数的函数名

因此,我的日志类中有一个名为
Write
的静态函数,它采用日志级别和变量列表。因此,我将其称为:

Log::Write(LOG_DEBUG, "this is an integer: %d", 10);
它将打印:

2013-01-02 => 10:12:01.366 [DEBUG]: this is an integer: 10
然而,我认为在消息中也包含调用者可能是有用的,以产生如下内容:

2013... => 10:12:... (functionName) [DEBUG]: blah
因此,我能做的(当然)是将
\uuuu func\uuu
作为参数添加到
Log::Write
,然而这意味着无论何时调用
Log::Write
,我都需要发送
\uu func\uuu
,它总是一样的,我觉得不需要明确说明就可以做到这一点

因此,我想要的是提供的功能:

Log::Write(LOG_DEBUG, __func__, "message");
无需每次都显式键入func

我不知道这是否真的是可能的,我的最佳选择是有某种方法可以在函数
Write
中取消对调用方的引用,我似乎不太可能“推断”出这样的参数。但至少值得一问,也许我可以看看有什么选择

谢谢

#define WRITE_LOG(X,...) Log::Write(LOG_DEBUG, __func__, (X),__VA_ARGS__);

使用此宏写入日志而不是函数,它将自动添加func参数。正如Mat所提到的,这是一种典型的方式,在这种情况下,我想不出任何办法来避免使用宏。

这通常是通过宏、文件名
\uuuuuuuuuuuuu
和行号
\uuuuuuuuuu
来完成的

void Log::Write(Level l,
                char const* function,
                char const* file,
                int line,
                char const* format,
                ...);
被包装到宏中:

#define LOG(Level_, Format_, ...) \
    Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__);
请注意,您可能希望通过检查是否以该级别登录来“保存”一些计算:

// suppose availability of "bool Log::Enabled(Level l)"
#define LOG(Level_, Format_, ...)   \
    while (Log::Enabled(Level_)) {  \
      Log::Write(Level_, __func__, __FILE__, __LINE__, Format_, __VA_ARGS__);  \
      break;  \
    }
使用
while
而不是
if
是为了避免挂起的else问题


注意:您可能希望调查使用流进行日志记录的情况。
printf
样式的问题在于它不可组合。对于流,您可以超载<代码> STD::OFSUCTORAND,这是“传统”的宏操作。C++中没有<代码>这是C99的一个附加,C++没有被收录。我怀疑大多数C++编译器会将它作为扩展(因为它们也是C编译器),但微软不这样做,我的经验表明,<代码>函数> <代码>,尽管它们不是标准的一部分,实际上更具可移植性。我相信
\uuuu func\uu
标识符是C++11的一个附加项,基本上它在任何函数中都可用,并且包含当前函数的名称。不过,我可能错了,但这是我的理解。我认为这样就可以了,它非常干净,完全解决了“问题”,谢谢。我没有想到这一点,可能应该在谷歌上多呆一段时间,或者在我看到它的时候多考虑一下。@qrikko-yup它应该能工作。您可以为每个日志级别创建一个不同的宏,或者将此宏修改为包含两个参数,如日志函数。请注意,这需要C++11。有更好的解决方案,根本不使用varargs:基本上,
Log::Write
返回一个
LogStream
对象,该对象具有模板化的
operator@JamesKanze我的目标是C++11,并在其中使用了很多功能,所以这对我来说不是问题,但这是一个有效的观点,应该注意!我也在后台使用ostreams,并且对varargs(旧的(可能是坏的)习惯)感觉更舒服,因此
Log::Write
实际上只是围绕另一个名为
get(short level)
的函数,该函数返回一个
ostream
引用,实际上,所有日志都是由
ostream
完成的。在这种情况下,如果(!Log::isEnabled(level)),则
if更容易处理悬空的else问题;否则…
。但存在更好的解决方案,完全避免了varargs。(而且
\uuuu VAR\u ARGS\uuuu
是C++11的一项功能,如果您关心可移植性的话,可能无法使用。)很多很棒的信息,谢谢!实际上,我正在使用ostream,因此我可以编写
Log::get(level)@JamesKanze:为了摆脱varargs,我倾向于切换到
ostream
日志。更方便(记录)。@qrikko:printf
-style和ostream
-style都有它们的用途
printf
-样式更易于国际化(因此向用户显示文本非常好),而
ostream
-样式更易于组合;谢天谢地,日志记录比国际化更需要可组合性。@MatthieuM。这是非常好的观点,谢谢你花时间也指出了这一点。正如我所说的,我确实是以ostream的方式开始的,但我只是有点“受损”,或者从Objc(通常只使用类似vararg的语法)来称呼它,所以我将ostream日志打包在一个函数中(
Write
)解析vararg并将它们发送到ostream,这只是一个坏习惯,我将开始使用ostream实现,甚至删除
Log::Write
函数,因为它对我来说只是“语法糖”。