summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant_p.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-06-10 11:26:31 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-13 08:48:32 +0200
commit048debe8f9a99bfd5db44b48657c4e1bc28c3448 (patch)
tree883b318fe4ba0bc99af320554d241cba66c8cfd6 /src/corelib/kernel/qvariant_p.h
parent4a69cd7f72140c8f4c83f986b3366f7bd9ba69a3 (diff)
Restrict QVariant::isNull() behavior
isNull() would forward to the contained type and check that type's isNull() method for some of the builtin types. Remove that behavior and only return true in isNull(), if the variant is invalid, doesn't contain data or contains a null pointer. In addition, implement more consistent behavior when constructing a QVariant using the internal API taking a copy from a void *. isNull() should return true in both cases. This mainly changes behavior for some corner cases and when using our internal API. [ChangeLog][Important Behavior Changes] QVariant::isNull() no longer returns true when the variant contains an object of some type with an isNull() method, that returns true for the object; QVariant::isNull() now only returns true when the variant contains no object or a null pointer. Change-Id: I3125041c4f8f8618a04aa375aa0a56b19c02dcf5 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/corelib/kernel/qvariant_p.h')
-rw-r--r--src/corelib/kernel/qvariant_p.h119
1 files changed, 0 insertions, 119 deletions
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 2cec8ff65b..56fd715382 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -182,127 +182,8 @@ inline void v_clear(QVariant::Private *d, T* = nullptr)
}
-template <typename T>
-struct PrimitiveIsNull
-{
-public:
- static bool isNull(const QVariant::Private *d)
- {
- return d->is_null;
- }
-};
-
-template <typename T>
-struct PrimitiveIsNull<T*>
-{
-public:
- static bool isNull(const QVariant::Private *d)
- {
- return d->is_null || d->data.ptr == nullptr;
- }
-};
-
-template <>
-struct PrimitiveIsNull<std::nullptr_t>
-{
-public:
- static bool isNull(const QVariant::Private *)
- {
- return true;
- }
-};
-
Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
-template<class Filter>
-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?
- template<typename T>
- class HasIsNullMethod {
- struct Yes { char unused[1]; };
- struct No { char unused[2]; };
- static_assert(sizeof(Yes) != sizeof(No));
-
- template<class C> static decltype(static_cast<const C*>(nullptr)->isNull(), Yes()) test(int);
- template<class C> static No test(...);
- public:
- static const bool Value = (sizeof(test<T>(0)) == sizeof(Yes));
- };
-
- // TODO This part should go to autotests during HasIsNullMethod generalization.
- static_assert(!HasIsNullMethod<bool>::Value);
- struct SelfTest1 { bool isNull() const; };
- static_assert(HasIsNullMethod<SelfTest1>::Value);
- struct SelfTest2 {};
- static_assert(!HasIsNullMethod<SelfTest2>::Value);
- struct SelfTest3 : public SelfTest1 {};
- static_assert(HasIsNullMethod<SelfTest3>::Value);
- struct SelfTestFinal1 final { bool isNull() const; };
- static_assert(HasIsNullMethod<SelfTestFinal1>::Value);
- struct SelfTestFinal2 final {};
- static_assert(!HasIsNullMethod<SelfTestFinal2>::Value);
- struct SelfTestFinal3 final : public SelfTest1 {};
- static_assert(HasIsNullMethod<SelfTestFinal3>::Value);
-
- template<typename T, bool HasIsNull = HasIsNullMethod<T>::Value>
- struct CallFilteredIsNull
- {
- static bool isNull(const QVariant::Private *d)
- {
- return v_cast<T>(d)->isNull();
- }
- };
- template<typename T>
- struct CallFilteredIsNull<T, /* HasIsNull = */ false>
- {
- static bool isNull(const QVariant::Private *d)
- {
- return PrimitiveIsNull<T>::isNull(d);
- }
- };
-
- template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted>
- struct CallIsNull
- {
- static bool isNull(const QVariant::Private *d)
- {
- return CallFilteredIsNull<T>::isNull(d);
- }
- };
- template<typename T>
- struct CallIsNull<T, /* IsAcceptedType = */ false>
- {
- static bool isNull(const QVariant::Private *d)
- {
- return CallFilteredIsNull<T, false>::isNull(d);
- }
- };
-
-public:
- QVariantIsNull(const QVariant::Private *d)
- : m_d(d)
- {}
- template<typename T>
- bool delegate(const T*)
- {
- return CallIsNull<T>::isNull(m_d);
- }
- // we need that as sizof(void) is undefined and it is needed in HasIsNullMethod
- 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 *)
- {
- // QVariantIsNull is used only for built-in types
- Q_ASSERT(false);
- return m_d->is_null;
- }
-protected:
- const QVariant::Private *m_d;
-};
-
namespace QVariantPrivate {
Q_CORE_EXPORT void registerHandler(const int /* Modules::Names */ name, const QVariant::Handler *handler);
}