Krupip
Krupip

Reputation: 4892

Get the id of a declared QMetaType at compile time?

I'm trying to register std::string for use with QVariant, and have it convert to another type which also functions as a variant, but is needed for serialization. I tried to do this with the following code:

Q_DECLARE_METATYPE (std::string)


const int std_string_enum = qMetaTypeId<std::string>();


void to_example_type(example_type &j, const QVariant &q_variant) {
qRegisterMetaType<std::string>("std::string");
    switch (q_variant.userType()) {
        case QMetaType::Bool:
            j = q_variant.value<bool>();
            break;
        case QMetaType::Int:
            j = q_variant.value<int>();
            break;
        case QMetaType::UInt:
            j = q_variant.value<unsigned int>();
            break;
        case QMetaType::Double:
            j = q_variant.value<double>();
            break;
        case QMetaType::Long:
            j = q_variant.value<long>();
            break;
        case QMetaType::LongLong:
            j = q_variant.value<long long>();
            break;
        case QMetaType::Short:
            j = q_variant.value<short>();
            break;
        case QMetaType::Char:
            j = q_variant.value<char>();
            break;
        case QMetaType::ULong:
            j = q_variant.value<unsigned long>();
            break;
        case QMetaType::ULongLong:
            j = q_variant.value<unsigned long long>();
            break;
        case QMetaType::UShort:
            j = q_variant.value<unsigned short>();
            break;
        case QMetaType::UChar:
            j = q_variant.value<unsigned char>();
            break;
        case QMetaType::Float:
            j = q_variant.value<unsigned char>();
            break;
        case QMetaType::QString:
            j = (q_variant.value<QString>()).toStdString();
        case std_string_enum:
            j = q_variant.value<std::string>();
            break;
        default:
            assert((false, "Can't Convert to example_type"));
            break;
    }
}

but was met with the following error:

error: the value of 'std_string_enum' is not usable in a constant expression

     case std_string_enum:

note: 'std_string_enum' was not initialized with a constant expression
 const int std_string_enum = qMetaTypeId<std::string>();

note: 'static constexpr int QMetaTypeId2<T>::qt_metatype_id() [with T = std::__cxx11::basic_string<char>]' is not usable as a constexpr function because:
     static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }

If I declare it instead constant expression:

constexpr int std_string_enum = qMetaTypeId<std::string>();

I get the following error:

in constexpr expansion of 'qMetaTypeId<std::__cxx11::basic_string<char> >()'

error: 'static constexpr int QMetaTypeId2<T>::qt_metatype_id() [with T = std::__cxx11::basic_string<char>]' called in a constant expression
     return QMetaTypeId2<T>::qt_metatype_id();

note: 'static constexpr int QMetaTypeId2<T>::qt_metatype_id() [with T = std::__cxx11::basic_string<char>]' is not usable as a constexpr function because:
     static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }

error: call to non-constexpr function 'static int QMetaTypeId<std::__cxx11::basic_string<char> >::qt_metatype_id()'
 static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }

I'm confused by this error, as the documentation states (emphasis mine):

Returns the meta type id of type T at compile time. If the type was not declared with Q_DECLARE_METATYPE(), compilation will fail.

After googling this, I found this correspondence, which was only available through a third party archival site as google hadn't cached the results:

Post by a***@fastmail.fm Thiago - The qMetaTypeId documentation (http://qt-project.org/doc/qt-5.1/qtcore/qmetatype.html#qMetaTypeId) specifically states that the type registration using this function is resolved at compile-time, not run-time.

The documentation is wrong. What Stephen said is correct.

however this was made 5 years ago, and I'm skeptical that the documentation wouldn't have been corrected or been proven correct in that time!

This seems like a fairly common problem in order to use qvariants with other systems, what if anything can I do to properly use QVariant in this scenario? Is there some way I can get the ID at compile time?

Note I'm using C++ 14 with Qt 5.8, if I need to upgrade qt however I can.

EDIT:

I've upgraded my mingw-64 version and my QT version, it still gives the same error. Additionally I've tried just registering a blank struct like so:

struct Test{
};
Q_DECLARE_METATYPE (Test)


const int test_enum= qMetaTypeId<Test>();

and it doesn't work

Upvotes: 2

Views: 1044

Answers (0)

Related Questions