Details
-
Bug
-
Resolution: Won't Do
-
Not Evaluated
-
None
-
5.15, 6.0, 6.8.1
-
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