如何避免许多#ifdef用于记录语句

时间:2013-10-22 17:14:09

标签: c++ c logging

在我们的应用程序中,我们创建了自己的日志记录系统。在此日志记录系统中,有几种不同的日志类型,调试,错误,警告,通信,性能和....有很多 #ifdef #endif 可以禁用特定的日志类型。这些 #ifdef #endif 会使代码难以阅读。

我们正在考虑删除这些 #ifdef #endif ,并在邮件写入文件之前进行检查。这意味着对日志系统有很多“无用的”调用。这些电话不会导致任何写作活动。

是否有更好方式打开/关闭日志类型,没有这些 #ifdef #endif AND 这些“无用的”来电?

2 个答案:

答案 0 :(得分:7)

以下内容如何:

// comment out if not needed
#define ENABLE_LOG

#ifdef ENABLE_LOG
#  define LOG(x) x
#else
#  define LOG(x) (void) 0 
#endif

稍后你可以打电话:

LOG(mylogger.call());

更新了#else部分,正如Dietrich Epp建议的那样。

答案 1 :(得分:7)

除了#define解决方案非常有效之外,我还想提供一个使用模板的替代方案

template<bool B>
void log(std::string message){}

template<>
void log<true>(std::string message){log_internal(message);}

#define DEBUG true
#define COMMUNICATION false

...

log<DEBUG>("this message will be logged");
log<COMMUNICATION>("this message won't");

对于大多数情况,#define解决方案确实很好,但有一些理由可以使用此解决方案:

  • 您可能需要确定范围 - 即不要让log设备弄脏全局命名空间。此解决方案可以放在namespace #define无法解决的地方。

  • 您可能需要更严格地控​​制可以做什么和不可以做什么。 LOG(x)定义存在以下问题:任何内容都可以放在x中 - 如果关闭日志记录,您将看不到问题。

要谨慎 - 您的代码可能会编译并使用

LOG(std::cout << "Here!" << endl);

因为此特定日志已关闭。但是从现在起2年后的某一天,有人会打开日志记录并在整个地方收到endl undefined错误。或者更糟糕的是 - 他可能会发现开启日志记录突然需要链接到一个早已消失的库(因为该日志特别称为此库中定义的函数),或者使用一个已经改变了界面的函数(甚至完全删除了!真实故事:()

修改

我被要求将其添加到答案中:

在你没有记录(空函数)的情况下,似乎有一个函数调用开销。情况并非如此,因为编译器会对其进行优化。如果你想确定这一点 - 在函数中添加inline指令。

此外,您可能希望将其从std::string更改为const char *,以确保不会调用任何字符串构造函数 - 但这也应该由编译器自动优化。

无论如何,就像我说的那样,本质上并不比#define解决方案好。实际上我仍然在我的项目中使用#define - 但是在某些特定情况下,这种模板解决方案更受欢迎。