summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.h
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-12 22:27:41 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-24 00:17:05 +0200
commit524edc7363ecb2ea2697ab17409705c277664e54 (patch)
tree9d9907d517e1867c4df500c9605f1782b3448fff /src/corelib/kernel/qvariant.h
parentbfbac6be753c8fa01345d7f9ea2f8bffc170337b (diff)
Clean up QVariant::Private::Data
Remove all the internal members of the union. Instead replace it with raw storage (uchar[]) aligned to max_align_t. Place all accesses to the internal members with get<> methods for consistency. Change-Id: Icebf46b90c9375aa6ea0b5913b2132608e8c223d Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io>
Diffstat (limited to 'src/corelib/kernel/qvariant.h')
-rw-r--r--src/corelib/kernel/qvariant.h58
1 files changed, 23 insertions, 35 deletions
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 419aefd081..258dac3bbc 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -352,7 +352,7 @@ class Q_CORE_EXPORT QVariant
void *data();
const void *constData() const
- { return d.is_shared ? d.data.shared->data() : &d.data.ptr; }
+ { return d.storage(); }
inline const void *data() const { return constData(); }
template<typename T, typename = std::enable_if_t<!std::is_same_v<std::decay_t<T>, QVariant>>>
@@ -442,7 +442,21 @@ class Q_CORE_EXPORT QVariant
};
struct Private
{
- Private() noexcept : packedType(0), is_shared(false), is_null(true) {}
+ static constexpr size_t MaxInternalSize = 3*sizeof(void *);
+ template<typename T>
+ static constexpr bool CanUseInternalSpace = (sizeof(T) <= MaxInternalSize);
+ static constexpr bool canUseInternalSpace(size_t s) { return s <= MaxInternalSize; }
+
+ alignas(std::max_align_t) union
+ {
+ uchar data[MaxInternalSize] = {};
+ PrivateShared *shared;
+ } data;
+ quintptr is_shared : 1;
+ quintptr is_null : 1;
+ quintptr packedType : sizeof(QMetaType) * 8 - 2;
+
+ Private() noexcept : is_shared(false), is_null(true), packedType(0) {}
explicit Private(const QMetaType &type) noexcept : is_shared(false), is_null(false)
{
if (type.d_ptr)
@@ -468,45 +482,19 @@ class Q_CORE_EXPORT QVariant
}
Q_CORE_EXPORT ~Private();
- union Data
- {
- void *threeptr[3] = { nullptr, nullptr, nullptr };
- char c;
- uchar uc;
- short s;
- signed char sc;
- ushort us;
- int i;
- uint u;
- long l;
- ulong ul;
- bool b;
- double d;
- float f;
- qreal real;
- qlonglong ll;
- qulonglong ull;
- QObject *o;
- void *ptr;
- PrivateShared *shared;
- } data;
- quintptr packedType : sizeof(QMetaType) * 8 - 2;
- quintptr is_shared : 1;
- quintptr is_null : 1;
-
- template<typename T>
- static constexpr bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data);
-
const void *storage() const
- { return is_shared ? data.shared->data() : &data; }
+ { return is_shared ? data.shared->data() : &data.data; }
const void *internalStorage() const
- { Q_ASSERT(is_shared); return &data; }
+ { Q_ASSERT(is_shared); return &data.data; }
// determine internal storage at compile time
template<typename T>
const T &get() const
- { return *static_cast<const T *>(CanUseInternalSpace<T> ? &data : data.shared->data()); }
+ { return *static_cast<const T *>(storage()); }
+ template<typename T>
+ void set(const T &t)
+ { *static_cast<T *>(CanUseInternalSpace<T> ? &data.data : data.shared->data()) = t; }
inline QMetaType type() const
{
@@ -750,7 +738,7 @@ namespace QtPrivate {
static T object(const QVariant &v)
{
return qobject_cast<T>(QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject
- ? v.d.data.o
+ ? v.d.get<QObject *>()
: QVariantValueHelper::metaType(v));
}
#endif