在我们的应用程序中,我们创建了自己的日志记录系统。在此日志记录系统中,有几种不同的日志类型,调试,错误,警告,通信,性能和....有很多 #ifdef 和 #endif 可以禁用特定的日志类型。这些 #ifdef 和 #endif 会使代码难以阅读。
我们正在考虑删除这些 #ifdef 和 #endif ,并在邮件写入文件之前进行检查。这意味着对日志系统有很多“无用的”调用。这些电话不会导致任何写作活动。
是否有更好方式打开/关闭日志类型,没有这些 #ifdef 和 #endif AND
这些“无用的”来电?
答案 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
- 但是在某些特定情况下,这种模板解决方案更受欢迎。