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>
This commit is contained in:
Ulf Hermann 2020-08-26 11:07:50 +02:00
parent dd5e4f54c8
commit e460addc42
2 changed files with 66 additions and 12 deletions

View File

@ -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;

View File

@ -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; }
};