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

qMetaTypeId violates constexpr rule

    XMLWordPrintable

Details

    • Bug
    • Resolution: Won't Do
    • Not Evaluated
    • None
    • 5.15, 6.0, 6.8.1
    • Core: Object Model
    • None

    Description

      We have currently following following line in our code:

       

      const int typeId = qMetaTypeId<property_t>();
      

      This line causes the MSVC warning C26814
       

      The const variable 'typeId' can be computed at compile-time. Consider using constexpr (con.5).
       

      Changing this line to
       

      constexpr int typeId = qMetaTypeId<property_t>();
      

      leads to a compile error C3615:

       

      constexpr function 'qMetaTypeId' cannot result in a constant expression
       

      Reason for this (code was adjusted here: 33cd680)

      inline constexpr int qMetaTypeId()
      {
          if constexpr (bool(QMetaTypeId2<T>::IsBuiltIn)) {
              // this has the same result as the below code, but avoids asking the
              // compiler to load a global variable whose value we know at compile
              // time
              return QMetaTypeId2<T>::MetaType;
          } else {
              return QMetaType::fromType<T>().id();
          }
      }
      

      In case of the IsBuiltIn case, the constexpr is correct. But in the other case not, as id() is not constexpr.

      Therefore it violates the rule: The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time.

      Note: This was already an issue in Qt 5:

      constexpr function 'QMetaTypeId2<QDir>::qt_metatype_id' cannot result in a constant expression
      

      Possible fix:
      Option 1) Just remove the constexpr
      Option 2) In case the method is should be constexpr for built-in types:

      template <typename T, std::enable_if_t<QMetaTypeId2<T>::IsBuiltIn, int> = 0> constexpr int qMetaTypeId()
      {
           return QMetaTypeId2<T>::MetaType;
      }
      
      template <typename T, std::enable_if_t<!QMetaTypeId2<T>::IsBuiltIn, int> = 0> inline int qMetaTypeId()
      {
           return QMetaType::fromType<T>().id();
      }
      

      I think option 1 is better, as option 2 improves slightly the compiler output, but basically it still requires:

      if constexpr (QMetaTypeId2<property_t>::IsBuiltIn)
      {
           constexpr int typeId = qMetaTypeId<property_t>();
      
           // my code
      } else {
           int typeId = qMetaTypeId<property_t>();
      
           // my code (copy & pase)
      }
      

      Therefore I think it is better to force user to call QMetaTypeId2<T>::MetaType directly in case they need it constexpr

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            EliteScience Heiko Thiel
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes