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

5Yr*_*DBA 5 c c++ logging

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

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

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

Sig*_*oad 7

以下内容如何:

// comment out if not needed
#define ENABLE_LOG

#ifdef ENABLE_LOG
#  define LOG(x) x
#else
#  define LOG(x) (void) 0 
#endif
Run Code Online (Sandbox Code Playgroud)

稍后你可以打电话:

LOG(mylogger.call());
Run Code Online (Sandbox Code Playgroud)

更新了#elseDietrich Epp建议的部件.

  • 我推荐`define LOG(x)(void)0`用于`else`分支,因为它不会为额外的分号生成编译器警告. (5认同)

rab*_*sky 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");
Run Code Online (Sandbox Code Playgroud)

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

  • 您可能需要确定范围 - 即不要让您的log设备弄脏全局命名空间.该解决方案可以被置于namespace其中#define一不可.

  • 您可能需要更严格地控​​制可以做什么和不可以做什么.该LOG(x)定义有什么都可以放在这个问题x-如果日志被关闭,你不会看到一个问题.

为了克劳 - 你的代码可以编译和使用

LOG(std::cout << "Here!" << endl);
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

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

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

无论如何,就像我说的那样,本质上并不比#define解决方案更好.我实际上仍然#define在我的项目中使用 - 但是有一些特定的实例,这个模板解决方案更可取.