diff options
Diffstat (limited to 'src/corelib/kernel/qvariant_p.h')
-rw-r--r-- | src/corelib/kernel/qvariant_p.h | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index a754bc4363..90756d76cc 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -187,7 +187,11 @@ public: return FilteredComparator<T>::compare(m_a, m_b); } - bool delegate(const void*) { return true; } + bool delegate(const void*) { Q_ASSERT(false); return true; } + bool delegate(const QMetaTypeSwitcher::UnknownType*) + { + return true; // for historical reason invalid variant == invalid variant + } bool delegate(const QMetaTypeSwitcher::NotBuiltinType*) { return false; } protected: const QVariant::Private *m_a; @@ -203,6 +207,19 @@ class QVariantIsNull /// \internal /// This class checks if a type T has method called isNull. Result is kept in the Value property /// TODO Can we somehow generalize it? A macro version? +#if defined(Q_COMPILER_DECLTYPE) // C++11 version + template<typename T> + class HasIsNullMethod { + struct Yes { char unused[1]; }; + struct No { char unused[2]; }; + Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); + + template<class C> static decltype(static_cast<const C*>(0)->isNull(), Yes()) test(int); + template<class C> static No test(...); + public: + static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes)); + }; +#else // C++98 version (doesn't work for final classes) template<typename T, bool IsClass = QTypeInfo<T>::isComplex> class HasIsNullMethod { @@ -211,7 +228,7 @@ class QVariantIsNull Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); struct FallbackMixin { bool isNull() const; }; - struct Derived : public T, public FallbackMixin {}; + struct Derived : public T, public FallbackMixin {}; // <- doesn't work for final classes template<class C, C> struct TypeCheck {}; template<class C> static Yes test(...); @@ -227,6 +244,7 @@ class QVariantIsNull public: static const bool Value = false; }; +#endif // TODO This part should go to autotests during HasIsNullMethod generalization. Q_STATIC_ASSERT(!HasIsNullMethod<bool>::Value); @@ -236,6 +254,12 @@ class QVariantIsNull Q_STATIC_ASSERT(!HasIsNullMethod<SelfTest2>::Value); struct SelfTest3 : public SelfTest1 {}; Q_STATIC_ASSERT(HasIsNullMethod<SelfTest3>::Value); + struct SelfTestFinal1 Q_DECL_FINAL_CLASS { bool isNull() const; }; + Q_STATIC_ASSERT(HasIsNullMethod<SelfTestFinal1>::Value); + struct SelfTestFinal2 Q_DECL_FINAL_CLASS {}; + Q_STATIC_ASSERT(!HasIsNullMethod<SelfTestFinal2>::Value); + struct SelfTestFinal3 Q_DECL_FINAL_CLASS : public SelfTest1 {}; + Q_STATIC_ASSERT(HasIsNullMethod<SelfTestFinal3>::Value); template<typename T, bool HasIsNull = HasIsNullMethod<T>::Value> struct CallFilteredIsNull @@ -281,7 +305,8 @@ public: return CallIsNull<T>::isNull(m_d); } // we need that as sizof(void) is undefined and it is needed in HasIsNullMethod - bool delegate(const void *) { return m_d->is_null; } + bool delegate(const void *) { Q_ASSERT(false); return m_d->is_null; } + bool delegate(const QMetaTypeSwitcher::UnknownType *) { return m_d->is_null; } bool delegate(const QMetaTypeSwitcher::NotBuiltinType *) { return m_d->is_null; } protected: const QVariant::Private *m_d; @@ -354,8 +379,18 @@ public: void delegate(const void*) { - // QMetaType::Void == QVariant::Invalid, creating an invalid value creates invalid QVariant - // TODO it might go away, check is needed + qWarning("Trying to create a QVariant instance of QMetaType::Void type, an invalid QVariant will be constructed instead"); + m_x->type = QMetaType::UnknownType; + m_x->is_shared = false; + m_x->is_null = !m_copy; + } + + void delegate(const QMetaTypeSwitcher::UnknownType*) + { + if (m_x->type != QMetaType::UnknownType) { + qWarning("Trying to construct an instance of an invalid type, type id: %i", m_x->type); + m_x->type = QMetaType::UnknownType; + } m_x->is_shared = false; m_x->is_null = !m_copy; } @@ -401,7 +436,8 @@ public: qWarning("Trying to destruct an instance of an invalid type, type id: %i", m_d->type); } // Ignore nonconstructible type - void delegate(const void*) {} + void delegate(const QMetaTypeSwitcher::UnknownType*) {} + void delegate(const void*) { Q_ASSERT(false); } private: QVariant::Private *m_d; }; @@ -446,10 +482,11 @@ public: { qWarning("Trying to stream an instance of an invalid type, type id: %i", m_d->type); } - void delegate(const void*) + void delegate(const QMetaTypeSwitcher::UnknownType*) { m_debugStream.nospace() << "QVariant::Invalid"; } + void delegate(const void*) { Q_ASSERT(false); } private: QDebug m_debugStream; QVariant::Private *m_d; |