summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qiterable.h
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-08-26 11:07:50 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-11 11:30:57 +0200
commite460addc423e6149f8d7dcfac19f87f8c08743aa (patch)
tree3110ee2232c1ba3eda0ce67e90361a2a776e311e /src/corelib/kernel/qiterable.h
parentdd5e4f54c8341f38b452bb0cc6d8ecfcf4f4cadc (diff)
Prepare QSequentialIterable for non-const operation
Introduce a smart pointer that saves its constness, even if the constness of the parent object changes. This allows us to implement the const and mutable iterators in the same class. Change-Id: I156e564c7fa2ecc8981c6d71861d796a5cbfec66 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/corelib/kernel/qiterable.h')
-rw-r--r--src/corelib/kernel/qiterable.h60
1 files changed, 57 insertions, 3 deletions
diff --git a/src/corelib/kernel/qiterable.h b/src/corelib/kernel/qiterable.h
index ac048547b5..a38fd8d184 100644
--- a/src/corelib/kernel/qiterable.h
+++ b/src/corelib/kernel/qiterable.h
@@ -44,13 +44,66 @@
#include <QtCore/qtypeinfo.h>
#include <QtCore/qmetacontainer.h>
#include <QtCore/qmetatype.h>
+#include <QtCore/qtaggedpointer.h>
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+ template<typename Type, typename Storage = Type>
+ class QConstPreservingPointer
+ {
+ enum Tag : bool { Const, Mutable };
+ QTaggedPointer<Storage, Tag> m_pointer;
+
+ public:
+ QConstPreservingPointer(std::nullptr_t) : m_pointer(nullptr, Const) {}
+
+ QConstPreservingPointer(const void *pointer, qsizetype alignment)
+ : m_pointer(reinterpret_cast<Storage *>(const_cast<void *>(pointer)), Const)
+ {
+ Q_UNUSED(alignment);
+ Q_ASSERT(alignment > qsizetype(alignof(Storage)));
+ }
+
+ QConstPreservingPointer(void *pointer, qsizetype alignment)
+ : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
+ {
+ Q_UNUSED(alignment);
+ Q_ASSERT(alignment > qsizetype(alignof(Storage)));
+ }
+
+ template<typename InputType>
+ QConstPreservingPointer(const InputType *pointer)
+ : m_pointer(reinterpret_cast<Storage *>(const_cast<InputType *>(pointer)), Const)
+ {
+ static_assert(alignof(InputType) >= alignof(Storage));
+ }
+
+ template<typename InputType>
+ QConstPreservingPointer(InputType *pointer)
+ : m_pointer(reinterpret_cast<Storage *>(pointer), Mutable)
+ {
+ static_assert(alignof(InputType) >= alignof(Storage));
+ }
+
+ QConstPreservingPointer() = default;
+
+ const Type *constPointer() const
+ {
+ return reinterpret_cast<const Type *>(m_pointer.data());
+ }
+
+ Type *mutablePointer() const
+ {
+ return m_pointer.tag() == Mutable ? reinterpret_cast<Type *>(m_pointer.data()) : nullptr;
+ }
+ };
+}
+
class Q_CORE_EXPORT QSequentialIterable
{
uint m_revision = 0;
- const void *m_iterable = nullptr;
+ QtPrivate::QConstPreservingPointer<void, quint16> m_iterable;
QMetaSequence m_metaSequence;
public:
@@ -97,7 +150,8 @@ public:
QSequentialIterable() = default;
- QSequentialIterable(const QMetaSequence &metaSequence, const void *iterable)
+ template<typename Pointer>
+ QSequentialIterable(const QMetaSequence &metaSequence, Pointer iterable)
: m_iterable(iterable)
, m_metaSequence(metaSequence)
{
@@ -111,7 +165,7 @@ public:
bool canReverseIterate() const;
- const void *constIterable() const { return m_iterable; }
+ const void *constIterable() const { return m_iterable.constPointer(); }
QMetaSequence metaSequence() const { return m_metaSequence; }
};