5

我正在用 C++ 实现一个日志处理程序,它工作得很好,但是我发现有一件事是可用的,那就是记录器从哪里获得输出。

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

所以我在我的 Log 类中有一个名为 的静态函数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

所以我可以做的(当然)是将__func__作为参数添加到Log::Write,但这意味着任何时候我打电话Log::Write我也需要发送__func__它总是相同的,我觉得应该可以在没有的情况下做到这一点明确表示。

所以我想要的是将提供的功能:

Log::Write(LOG_DEBUG, __func__, "message");

无需每次都显式输入func 。

我不知道这是否真的可行,我最好的选择是有一些方法可以取消引用函数内部的调用者Write,我似乎不太可能只是“推断”这样的参数. 但至少值得一问,也许我可以看到有哪些选择。

谢谢。

4

2 回答 2

8

这通常使用宏以及文件名__FILE__和行号来完成__LINE__

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;  \
    }

使用 awhile而不是if是为了避免悬空的 else 问题。

注意:您可能希望调查使用流进行日志记录。样式的问题printf在于它是不可组合的。使用流,您可以重载std::ostream& operator<<(std::ostream&, X const&)任何内容X,然后只编写一次将其内容转储到日志中的方法。

于 2013-01-02T09:32:05.607 回答
3
#define WRITE_LOG(X,...) Log::Write(LOG_DEBUG, __func__, (X),__VA_ARGS__);

用这个宏代替函数写日志,它会自动添加func参数。正如 Mat 提到的,这是典型的方式,在这种情况下我想不出任何方法来避免宏。

于 2013-01-02T09:27:00.410 回答