【问题标题】:Why is qCDebug() macro defined in the way it is?为什么 qCDebug() 宏是这样定义的?
【发布时间】:2021-07-02 07:26:25
【问题描述】:

qCDebug() 宏有一个简单的声明,但是使用“degenerate for-loop”而不是简单直接的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__)

?

【问题讨论】:

    标签: c++ qt coding-style


    【解决方案1】:

    看例子。

    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
    

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

    【讨论】:

    • else (void)0 的解决方案没有完成,因为该宏应该以下列方式使用:qCDebug(cat) << "my log message"; 因此宏应该以“打开”的 QMessageLogger 对象结尾。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多