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:
parent
dd5e4f54c8
commit
e460addc42
@ -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;
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user