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/kernel/qiterable.h | |
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/kernel/qiterable.h')
-rw-r--r-- | src/corelib/kernel/qiterable.h | 60 |
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; } }; |