为什么 qCDebug() 宏是这样定义的?

Why is qCDebug() macro defined in the way it is?

qCDebug() 宏有一个简单的声明,但是使用“退化for-循环”而不是简单明了的if有什么好处?

    #define qCDebug(category, ...) \
        for (bool qt_category_enabled = category().isDebugEnabled(); qt_category_enabled; qt_category_enabled = false) \
            QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__)

现代编译器在优化高于 -O0 的情况下给出相同的结果,所以这不应该是原因。

循环体中没有使用变量qt_category_enabled

将其用作宏似乎也不需要副作用,例如添加另一层作用域。

那么,为什么不

    #define qCDebug(category, ...) \
        if (category().isDebugEnabled()) \
            QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__)

?

看例子。

if (condition)
  qCDebug(...);
else
  exit(0);

如果使用 for 循环,扩展代码的行为符合预期。

if (condition)
  for (...; category().isDebugEnabled(); ...)
    QMessageLogger(...);
else
  exit(0);

在 if-condition 的情况下,else-branch 总是附加到最近的 if,并且你得到扩展代码

if (condition)
  if (category().isDebugEnabled())
    QMessageLogger(...);
  else
    exit(0);

看出区别了吗?

这个错误可以通过定义像

这样的宏来修复
#define qCDebug(category, ...) \
  if (category().isDebugEnabled()) \
    QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC, category().categoryName()).debug(__VA_ARGS__); \
  else (void)0

为什么不这样做,是一个基于意见的问题。