Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-77216

Q_FLAG documentation erroneously suggests to apply it to QFlags instead of enum itself

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.13.2, 5.14.0 Beta 1
    • 5.9.4
    • None
    • openSUSE Leap 15.0
      4.12.14-lp150.12.67-default
      gcc (SUSE Linux) 7.4.1 20190424 [gcc-7-branch revision 270538]
      QMake version 3.1
      Using Qt version 5.9.4
    • All
    • 1872d1a41de0d4994c799c8d7dd4e72aaf49c677 (qt/qtbase/5.13)

    Description

      The Qt behavior strongly suggests that if you have an enum acting like a set of flags and you’ve declared a QFlags type using Q_DECLARE_FLAGS macro, then you should apply the Q_FLAG macro to the enumeration itself, and not to the QFlags type.

      1. If you use Q_FLAG on the enum, then both the enum and corresponding QFlags are stringified by qDebug() properly. If you follow the documentation, QFlags is stringified properly while enum itself is not.
      2. If you use Q_FLAG on the enum, dumping a QFlags variable to qDebug() produces a string which looks like
        QFlags<EnumName>(EnumValue)
        , which is correct. If you follow the documentation, QDebug produces a string which looks like
        QFlags<QFlagsName>(EnumValue)
        , which is misleading and semantically wrong.

      The QObject class reference says this:

      It is typically used in a class definition to declare that values of a given enum can be used as flags and combined using the bitwise OR operator.

      This is marginally acceptable in the sense that it can be understood that Q_FLAG should be applied to the enumeration itself. However, it’s followed by an example which does this:

      ...
      Q_DECLARE_FLAGS(LoadHints, LoadHint)
      Q_FLAG(LoadHints)

      This error in documentation is so misleading that it confused the overwhelming majority of Qt developers themselves, which lead to 75% of Qt enums to be marked in a wrong way. Anyone can check this with a tiny program:

      // BAD: outputs 1 instead of the name
      qDebug() << Qt::AlignLeading;

      // BAD (although somewhat acceptable): outputs
      // QFlags<Qt::Alignment>(AlignLeading|AlignTrailing)
      // instead of semantically correct
      // QFlags<Qt::AlignmentFlag>(AlignLeading|AlignTrailing)
      // or, which would be less cumbersome and easier to read,
      // Qt::Alignment(AlignLeading|AlignTrailing)
      qDebug() << Qt::Alignment(Qt::AlignLeading | Qt::AlignTrailing);

       

      Please note that the attached SSCCE contains additional info.

      Attachments

        For Gerrit Dashboard: QTBUG-77216
        # Subject Branch Project Status CR V

        Activity

          People

            thiago Thiago Macieira
            scumcoder Daniil Larionov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes