6

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

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

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

4

2 回答 2

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 的建议更新了该部分。

于 2013-10-22T17:20:29.583 回答
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向函数添加指令。

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

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

于 2013-10-22T18:15:15.870 回答