diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-08-26 11:07:50 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-09-11 11:30:57 +0200 |
commit | e460addc423e6149f8d7dcfac19f87f8c08743aa (patch) | |
tree | 3110ee2232c1ba3eda0ce67e90361a2a776e311e /src/corelib | |
parent | dd5e4f54c8341f38b452bb0cc6d8ecfcf4f4cadc (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')
-rw-r--r-- | src/corelib/kernel/qiterable.cpp | 18 | ||||
-rw-r--r-- | src/corelib/kernel/qiterable.h | 60 |
2 files changed, 66 insertions, 12 deletions
diff --git a/src/corelib/kernel/qiterable.cpp b/src/corelib/kernel/qiterable.cpp index f1c2512f36..d215296906 100644 --- a/src/corelib/kernel/qiterable.cpp +++ b/src/corelib/kernel/qiterable.cpp @@ -74,7 +74,7 @@ QSequentialIterable::const_iterator::const_iterator(const QSequentialIterable *i */ QSequentialIterable::const_iterator QSequentialIterable::begin() const { - return const_iterator(this, m_metaSequence.constBegin(m_iterable)); + return const_iterator(this, m_metaSequence.constBegin(m_iterable.constPointer())); } /*! @@ -85,7 +85,7 @@ QSequentialIterable::const_iterator QSequentialIterable::begin() const */ QSequentialIterable::const_iterator QSequentialIterable::end() const { - return const_iterator(this, m_metaSequence.constEnd(m_iterable)); + return const_iterator(this, m_metaSequence.constEnd(m_iterable.constPointer())); } /*! @@ -102,9 +102,9 @@ QVariant QSequentialIterable::at(qsizetype idx) const const QMetaSequence metaSequence = m_metaSequence; if (metaSequence.canGetElementAtIndex()) { - metaSequence.elementAtIndex(m_iterable, idx, dataPtr); + metaSequence.elementAtIndex(m_iterable.constPointer(), idx, dataPtr); } else if (metaSequence.canGetElementAtConstIterator()) { - void *iterator = metaSequence.constBegin(m_iterable); + void *iterator = metaSequence.constBegin(m_iterable.constPointer()); metaSequence.advanceConstIterator(iterator, idx); metaSequence.elementAtConstIterator(iterator, dataPtr); metaSequence.destroyConstIterator(iterator); @@ -119,7 +119,7 @@ QVariant QSequentialIterable::at(qsizetype idx) const qsizetype QSequentialIterable::size() const { const QMetaSequence metaSequence = m_metaSequence; - const void *container = m_iterable; + const void *container = m_iterable.constPointer(); if (metaSequence.hasSize()) return metaSequence.size(container); if (!metaSequence.hasConstIterator()) @@ -261,7 +261,7 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato { const_iterator result( m_iterable, - m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer())); m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); m_iterable->m_metaSequence.advanceConstIterator(m_iterator, 1); return result; @@ -299,7 +299,7 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato { const_iterator result( m_iterable, - m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer())); m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); m_iterable->m_metaSequence.advanceConstIterator(m_iterator, -1); return result; @@ -340,7 +340,7 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato { const_iterator result( m_iterable, - m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer())); m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, j); return result; @@ -359,7 +359,7 @@ QSequentialIterable::const_iterator QSequentialIterable::const_iterator::operato { const_iterator result( m_iterable, - m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable)); + m_iterable->m_metaSequence.constBegin(m_iterable->m_iterable.constPointer())); m_iterable->m_metaSequence.copyConstIterator(result.m_iterator, m_iterator); m_iterable->m_metaSequence.advanceConstIterator(result.m_iterator, -j); return result; 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; } }; |