summaryrefslogtreecommitdiffstats
path: root/src/corelib
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
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')
-rw-r--r--src/corelib/kernel/qiterable.cpp18
-rw-r--r--src/corelib/kernel/qiterable.h60
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; }
};