summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetacontainer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qmetacontainer.cpp')
-rw-r--r--src/corelib/kernel/qmetacontainer.cpp831
1 files changed, 831 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmetacontainer.cpp b/src/corelib/kernel/qmetacontainer.cpp
new file mode 100644
index 0000000000..5f68f8fe74
--- /dev/null
+++ b/src/corelib/kernel/qmetacontainer.cpp
@@ -0,0 +1,831 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmetacontainer.h"
+#include "qmetatype.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaSequence
+ \inmodule QtCore
+ \since 6.0
+ \brief The QMetaSequence class allows type erased access to sequential containers.
+
+ \ingroup objectmodel
+
+ \compares equality
+
+ The class provides a number of primitive container operations, using void*
+ as operands. This way, you can manipulate a generic container retrieved from
+ a Variant without knowing its type.
+
+ The void* arguments to the various methods are typically created by using
+ a \l QVariant of the respective container or value type, and calling
+ its \l QVariant::data() or \l QVariant::constData() methods. However, you
+ can also pass plain pointers to objects of the container or value type.
+
+ Iterator invalidation follows the rules given by the underlying containers
+ and is not expressed in the API. Therefore, for a truly generic container,
+ any iterators should be considered invalid after any write operation.
+*/
+
+/*!
+ \fn template<typename C> QMetaSequence QMetaSequence::fromContainer()
+ \since 6.0
+
+ Returns the QMetaSequence corresponding to the type given as template parameter.
+*/
+
+/*!
+ Returns \c true if the underlying container provides at least an input
+ iterator as defined by std::input_iterator_tag, otherwise returns
+ \c false. Forward, Bi-directional, and random access iterators are
+ specializations of input iterators. This method will also return
+ \c true if the container provides one of those.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasInputIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::InputCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides at least a forward
+ iterator as defined by std::forward_iterator_tag, otherwise returns
+ \c false. Bi-directional iterators and random access iterators are
+ specializations of forward iterators. This method will also return
+ \c true if the container provides one of those.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasForwardIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::ForwardCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides a bi-directional
+ iterator or a random access iterator as defined by
+ std::bidirectional_iterator_tag and std::random_access_iterator_tag,
+ respectively. Otherwise returns \c false.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasBidirectionalIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::BiDirectionalCapability);
+}
+
+/*!
+ Returns \c true if the underlying container provides a random access
+ iterator as defined by std::random_access_iterator_tag, otherwise returns
+ \c false.
+
+ QMetaSequence assumes that const and non-const iterators for the same
+ container have the same iterator traits.
+ */
+bool QMetaContainer::hasRandomAccessIterator() const
+{
+ if (!d_ptr)
+ return false;
+ return d_ptr->iteratorCapabilities.testAnyFlag(QtMetaContainerPrivate::RandomAccessCapability);
+}
+
+/*!
+ Returns the meta type for values stored in the container.
+ */
+QMetaType QMetaSequence::valueMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->valueMetaType);
+ return QMetaType();
+}
+
+/*!
+ Returns \c true if the underlying container is sortable, otherwise returns
+ \c false. A container is considered sortable if values added to it are
+ placed in a defined location. Inserting into or adding to a sortable
+ container will always succeed. Inserting into or adding to an unsortable
+ container may not succeed, for example if the container is a QSet that
+ already contains the value being inserted.
+
+ \sa addValue(), insertValueAtIterator(), canAddValueAtBegin(),
+ canAddValueAtEnd(), canRemoveValueAtBegin(), canRemoveValueAtEnd()
+ */
+bool QMetaSequence::isSortable() const
+{
+ if (auto iface = d()) {
+ return (iface->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
+ && (iface->addRemoveCapabilities
+ & (QtMetaContainerPrivate::CanRemoveAtBegin
+ | QtMetaContainerPrivate::CanRemoveAtEnd));
+ }
+ return false;
+}
+
+/*!
+ Returns \c true if values added using \l addValue() can be placed at the
+ beginning of the container, otherwise returns \c false.
+
+ \sa addValueAtBegin(), canAddValueAtEnd()
+ */
+bool QMetaSequence::canAddValueAtBegin() const
+{
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
+ }
+ return false;
+}
+
+/*!
+ Adds \a value to the beginning of \a container if possible. If
+ \l canAddValueAtBegin() returns \c false, the \a value is not added.
+
+ \sa canAddValueAtBegin(), isSortable(), removeValueAtBegin()
+ */
+void QMetaSequence::addValueAtBegin(void *container, const void *value) const
+{
+ if (canAddValueAtBegin())
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values can be removed from the beginning of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtBegin(), canRemoveValueAtEnd()
+ */
+bool QMetaSequence::canRemoveValueAtBegin() const
+{
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the beginning of \a container if possible. If
+ \l canRemoveValueAtBegin() returns \c false, the value is not removed.
+
+ \sa canRemoveValueAtBegin(), isSortable(), addValueAtBegin()
+ */
+void QMetaSequence::removeValueAtBegin(void *container) const
+{
+ if (canRemoveValueAtBegin())
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+}
+
+/*!
+ Returns \c true if values added using \l addValue() can be placed at the
+ end of the container, otherwise returns \c false.
+
+ \sa addValueAtEnd(), canAddValueAtBegin()
+ */
+bool QMetaSequence::canAddValueAtEnd() const
+{
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Adds \a value to the end of \a container if possible. If
+ \l canAddValueAtEnd() returns \c false, the \a value is not added.
+
+ \sa canAddValueAtEnd(), isSortable(), removeValueAtEnd()
+ */
+void QMetaSequence::addValueAtEnd(void *container, const void *value) const
+{
+ if (canAddValueAtEnd())
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+}
+
+/*!
+ Returns \c true if values can be removed from the end of the container
+ using \l removeValue() can be placed at the, otherwise returns \c false.
+
+ \sa removeValueAtEnd(), canRemoveValueAtBegin()
+ */
+bool QMetaSequence::canRemoveValueAtEnd() const
+{
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
+ }
+ return false;
+}
+
+/*!
+ Removes a value from the end of \a container if possible. If
+ \l canRemoveValueAtEnd() returns \c false, the value is not removed.
+
+ \sa canRemoveValueAtEnd(), isSortable(), addValueAtEnd()
+ */
+void QMetaSequence::removeValueAtEnd(void *container) const
+{
+ if (canRemoveValueAtEnd())
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+}
+
+/*!
+ Returns \c true if the container can be queried for its size, \c false
+ otherwise.
+
+ \sa size()
+ */
+bool QMetaContainer::hasSize() const
+{
+ return d_ptr && d_ptr->sizeFn;
+}
+
+/*!
+ Returns the number of values in the given \a container if it can be
+ queried for its size. Otherwise returns \c -1.
+
+ \sa hasSize()
+ */
+qsizetype QMetaContainer::size(const void *container) const
+{
+ return hasSize() ? d_ptr->sizeFn(container) : -1;
+}
+
+/*!
+ Returns \c true if the container can be cleared, \c false otherwise.
+
+ \sa clear()
+ */
+bool QMetaContainer::canClear() const
+{
+ return d_ptr && d_ptr->clearFn;
+}
+
+/*!
+ Clears the given \a container if it can be cleared.
+
+ \sa canClear()
+ */
+void QMetaContainer::clear(void *container) const
+{
+ if (canClear())
+ d_ptr->clearFn(container);
+}
+
+/*!
+ Returns \c true if values can be retrieved from the container by index,
+ otherwise \c false.
+
+ \sa valueAtIndex()
+ */
+bool QMetaSequence::canGetValueAtIndex() const
+{
+ if (auto iface = d())
+ return iface->valueAtIndexFn;
+ return false;
+}
+
+/*!
+ Retrieves the value at \a index in the \a container and places it in the
+ memory location pointed to by \a result, if that is possible.
+
+ \sa canGetValueAtIndex()
+ */
+void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
+{
+ if (canGetValueAtIndex())
+ d()->valueAtIndexFn(container, index, result);
+}
+
+/*!
+ Returns \c true if an value can be written to the container by index,
+ otherwise \c false.
+
+ \sa setValueAtIndex()
+*/
+bool QMetaSequence::canSetValueAtIndex() const
+{
+ if (auto iface = d())
+ return iface->setValueAtIndexFn;
+ return false;
+}
+
+/*!
+ Overwrites the value at \a index in the \a container using the \a value
+ passed as parameter if that is possible.
+
+ \sa canSetValueAtIndex()
+ */
+void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
+{
+ if (canSetValueAtIndex())
+ d()->setValueAtIndexFn(container, index, value);
+}
+
+/*!
+ Returns \c true if values can be added to the container, \c false
+ otherwise.
+
+ \sa addValue(), isSortable()
+ */
+bool QMetaSequence::canAddValue() const
+{
+ if (auto iface = d())
+ return iface->addValueFn;
+ return false;
+}
+
+/*!
+ Adds \a value to the \a container if possible. If \l canAddValue()
+ returns \c false, the \a value is not added. Else, if
+ \l canAddValueAtEnd() returns \c true, the \a value is added
+ to the end of the \a container. Else, if
+ \l canAddValueAtBegin() returns \c true, the \a value is added to
+ the beginning of the container. Else, the value is added in an unspecified
+ place or not at all. The latter is the case for adding values to an
+ unordered container, for example \l QSet.
+
+ \sa canAddValue(), canAddValueAtBegin(),
+ canAddValueAtEnd(), isSortable(), removeValue()
+ */
+void QMetaSequence::addValue(void *container, const void *value) const
+{
+ if (canAddValue()) {
+ d()->addValueFn(container, value,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
+}
+
+/*!
+ Returns \c true if values can be removed from the container, \c false
+ otherwise.
+
+ \sa removeValue(), isSortable()
+ */
+bool QMetaSequence::canRemoveValue() const
+{
+ if (auto iface = d())
+ return iface->removeValueFn;
+ return false;
+}
+
+/*!
+ Removes an value from the \a container if possible. If
+ \l canRemoveValue() returns \c false, no value is removed. Else, if
+ \l canRemoveValueAtEnd() returns \c true, the last value in
+ the \a container is removed. Else, if \l canRemoveValueAtBegin()
+ returns \c true, the first value in the \a container is removed. Else,
+ an unspecified value or nothing is removed.
+
+ \sa canRemoveValue(), canRemoveValueAtBegin(),
+ canRemoveValueAtEnd(), isSortable(), addValue()
+ */
+void QMetaSequence::removeValue(void *container) const
+{
+ if (canRemoveValue()) {
+ d()->removeValueFn(container,
+ QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
+ }
+}
+
+/*!
+ Returns \c true if the underlying container offers a non-const iterator,
+ \c false otherwise.
+
+ \sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
+ advanceIterator(), copyIterator()
+ */
+bool QMetaContainer::hasIterator() const
+{
+ if (!d_ptr || !d_ptr->createIteratorFn)
+ return false;
+ Q_ASSERT(d_ptr->destroyIteratorFn);
+ Q_ASSERT(d_ptr->compareIteratorFn);
+ Q_ASSERT(d_ptr->copyIteratorFn);
+ Q_ASSERT(d_ptr->advanceIteratorFn);
+ Q_ASSERT(d_ptr->diffIteratorFn);
+ return true;
+}
+
+/*!
+ Creates and returns a non-const iterator pointing to the beginning of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any non-const iterators.
+
+ \sa end(), constBegin(), constEnd(), destroyIterator()
+ */
+void *QMetaContainer::begin(void *container) const
+{
+ return hasIterator()
+ ? d_ptr->createIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
+ : nullptr;
+}
+
+/*!
+ Creates and returns a non-const iterator pointing to the end of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any non-const iterators.
+
+ \sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
+ */
+void *QMetaContainer::end(void *container) const
+{
+ return hasIterator()
+ ? d_ptr->createIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
+ : nullptr;
+}
+
+/*!
+ Destroys a non-const \a iterator previously created using \l begin() or
+ \l end().
+
+ \sa begin(), end(), destroyConstIterator()
+ */
+void QMetaContainer::destroyIterator(const void *iterator) const
+{
+ if (hasIterator())
+ d_ptr->destroyIteratorFn(iterator);
+}
+
+/*!
+ Returns \c true if the non-const iterators \a i and \a j point to the same
+ value in the container they are iterating over, otherwise returns \c
+ false.
+
+ \sa begin(), end()
+ */
+bool QMetaContainer::compareIterator(const void *i, const void *j) const
+{
+ return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
+}
+
+/*!
+ Copies the non-const iterator \a source into the non-const iterator
+ \a target. Afterwards compareIterator(target, source) returns \c true.
+
+ \sa begin(), end()
+ */
+void QMetaContainer::copyIterator(void *target, const void *source) const
+{
+ if (hasIterator())
+ d_ptr->copyIteratorFn(target, source);
+}
+
+/*!
+ Advances the non-const \a iterator by \a step steps. If \a steps is negative
+ the \a iterator is moved backwards, towards the beginning of the container.
+ The behavior is unspecified for negative values of \a step if
+ \l hasBidirectionalIterator() returns false.
+
+ \sa begin(), end()
+ */
+void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
+{
+ if (hasIterator())
+ d_ptr->advanceIteratorFn(iterator, step);
+}
+
+/*!
+ Returns the distance between the non-const iterators \a i and \a j, the
+ equivalent of \a i \c - \a j. If \a j is closer to the end of the container
+ than \a i, the returned value is negative. The behavior is unspecified in
+ this case if \l hasBidirectionalIterator() returns false.
+
+ \sa begin(), end()
+ */
+qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
+{
+ return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
+}
+
+/*!
+ Returns \c true if the underlying container can retrieve the value pointed
+ to by a non-const iterator, \c false otherwise.
+
+ \sa hasIterator(), valueAtIterator()
+ */
+bool QMetaSequence::canGetValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->valueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Retrieves the value pointed to by the non-const \a iterator and stores it
+ in the memory location pointed to by \a result, if possible.
+
+ \sa canGetValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
+{
+ if (canGetValueAtIterator())
+ d()->valueAtIteratorFn(iterator, result);
+}
+
+/*!
+ Returns \c true if the underlying container can write to the value pointed
+ to by a non-const iterator, \c false otherwise.
+
+ \sa hasIterator(), setValueAtIterator()
+ */
+bool QMetaSequence::canSetValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->setValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Writes \a value to the value pointed to by the non-const \a iterator, if
+ possible.
+
+ \sa canSetValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
+{
+ if (canSetValueAtIterator())
+ d()->setValueAtIteratorFn(iterator, value);
+}
+
+/*!
+ Returns \c true if the underlying container can insert a new value, taking
+ the location pointed to by a non-const iterator into account.
+
+ \sa hasIterator(), insertValueAtIterator()
+ */
+bool QMetaSequence::canInsertValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->insertValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Inserts \a value into the \a container, if possible, taking the non-const
+ \a iterator into account. If \l canInsertValueAtIterator() returns
+ \c false, the \a value is not inserted. Else if \l isSortable() returns
+ \c true, the value is inserted before the value pointed to by
+ \a iterator. Else, the \a value is inserted at an unspecified place or not
+ at all. In the latter case, the \a iterator is taken as a hint. If it points
+ to the correct place for the \a value, the operation may be faster than a
+ \l addValue() without iterator.
+
+ \sa canInsertValueAtIterator(), isSortable(), begin(), end()
+ */
+void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
+ const void *value) const
+{
+ if (canInsertValueAtIterator())
+ d()->insertValueAtIteratorFn(container, iterator, value);
+}
+
+/*!
+ Returns \c true if the value pointed to by a non-const iterator can be
+ erased, \c false otherwise.
+
+ \sa hasIterator(), eraseValueAtIterator()
+ */
+bool QMetaSequence::canEraseValueAtIterator() const
+{
+ if (auto iface = d())
+ return iface->eraseValueAtIteratorFn;
+ return false;
+}
+
+/*!
+ Erases the value pointed to by the non-const \a iterator from the
+ \a container, if possible.
+
+ \sa canEraseValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
+{
+ if (canEraseValueAtIterator())
+ d()->eraseValueAtIteratorFn(container, iterator);
+}
+
+/*!
+ Returns \c true if a range between two iterators can be erased from the
+ container, \c false otherwise.
+ */
+bool QMetaSequence::canEraseRangeAtIterator() const
+{
+ if (auto iface = d())
+ return iface->eraseRangeAtIteratorFn;
+ return false;
+}
+
+/*!
+ Erases the range of values between the iterators \a iterator1 and
+ \a iterator2 from the \a container, if possible.
+
+ \sa canEraseValueAtIterator(), begin(), end()
+ */
+void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
+ const void *iterator2) const
+{
+ if (canEraseRangeAtIterator())
+ d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
+}
+
+/*!
+ Returns \c true if the underlying container offers a const iterator,
+ \c false otherwise.
+
+ \sa constBegin(), constEnd(), destroyConstIterator(),
+ compareConstIterator(), diffConstIterator(), advanceConstIterator(),
+ copyConstIterator()
+ */
+bool QMetaContainer::hasConstIterator() const
+{
+ if (!d_ptr || !d_ptr->createConstIteratorFn)
+ return false;
+ Q_ASSERT(d_ptr->destroyConstIteratorFn);
+ Q_ASSERT(d_ptr->compareConstIteratorFn);
+ Q_ASSERT(d_ptr->copyConstIteratorFn);
+ Q_ASSERT(d_ptr->advanceConstIteratorFn);
+ Q_ASSERT(d_ptr->diffConstIteratorFn);
+ return true;
+}
+
+/*!
+ Creates and returns a const iterator pointing to the beginning of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyConstIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any const iterators.
+
+ \sa constEnd(), begin(), end(), destroyConstIterator()
+ */
+void *QMetaContainer::constBegin(const void *container) const
+{
+ return hasConstIterator()
+ ? d_ptr->createConstIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin)
+ : nullptr;
+}
+
+/*!
+ Creates and returns a const iterator pointing to the end of
+ \a container. The iterator is allocated on the heap using new. It has to be
+ destroyed using \l destroyConstIterator eventually, to reclaim the memory.
+
+ Returns \c nullptr if the container doesn't offer any const iterators.
+
+ \sa constBegin(), begin(), end(), destroyConstIterator()
+ */
+void *QMetaContainer::constEnd(const void *container) const
+{
+ return hasConstIterator()
+ ? d_ptr->createConstIteratorFn(
+ container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd)
+ : nullptr;
+}
+
+/*!
+ Destroys a const \a iterator previously created using \l constBegin() or
+ \l constEnd().
+
+ \sa constBegin(), constEnd(), destroyIterator()
+ */
+void QMetaContainer::destroyConstIterator(const void *iterator) const
+{
+ if (hasConstIterator())
+ d_ptr->destroyConstIteratorFn(iterator);
+}
+
+/*!
+ Returns \c true if the const iterators \a i and \a j point to the same
+ value in the container they are iterating over, otherwise returns \c
+ false.
+
+ \sa constBegin(), constEnd()
+ */
+bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
+{
+ return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
+}
+
+/*!
+ Copies the const iterator \a source into the const iterator
+ \a target. Afterwards compareConstIterator(target, source) returns \c true.
+
+ \sa constBegin(), constEnd()
+ */
+void QMetaContainer::copyConstIterator(void *target, const void *source) const
+{
+ if (hasConstIterator())
+ d_ptr->copyConstIteratorFn(target, source);
+}
+
+/*!
+ Advances the const \a iterator by \a step steps. If \a steps is negative
+ the \a iterator is moved backwards, towards the beginning of the container.
+ The behavior is unspecified for negative values of \a step if
+ \l hasBidirectionalIterator() returns false.
+
+ \sa constBegin(), constEnd()
+ */
+void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
+{
+ if (hasConstIterator())
+ d_ptr->advanceConstIteratorFn(iterator, step);
+}
+
+/*!
+ Returns the distance between the const iterators \a i and \a j, the
+ equivalent of \a i \c - \a j. If \a j is closer to the end of the container
+ than \a i, the returned value is negative. The behavior is unspecified in
+ this case if \l hasBidirectionalIterator() returns false.
+
+ \sa constBegin(), constEnd()
+ */
+qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
+{
+ return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
+}
+
+/*!
+ Returns \c true if the underlying container can retrieve the value pointed
+ to by a const iterator, \c false otherwise.
+
+ \sa hasConstIterator(), valueAtConstIterator()
+ */
+bool QMetaSequence::canGetValueAtConstIterator() const
+{
+ if (auto iface = d())
+ return iface->valueAtConstIteratorFn;
+ return false;
+}
+
+/*!
+ Retrieves the value pointed to by the const \a iterator and stores it
+ in the memory location pointed to by \a result, if possible.
+
+ \sa canGetValueAtConstIterator(), constBegin(), constEnd()
+ */
+void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
+{
+ if (canGetValueAtConstIterator())
+ d()->valueAtConstIteratorFn(iterator, result);
+}
+
+/*!
+ \fn bool QMetaSequence::operator==(const QMetaSequence &lhs, const QMetaSequence &rhs)
+ \since 6.0
+
+ Returns \c true if the QMetaSequence \a lhs represents the same container type
+ as the QMetaSequence \a rhs, otherwise returns \c false.
+*/
+
+/*!
+ \fn bool QMetaSequence::operator!=(const QMetaSequence &lhs, const QMetaSequence &rhs)
+ \since 6.0
+
+ Returns \c true if the QMetaSequence \a lhs represents a different container
+ type than the QMetaSequence \a rhs, otherwise returns \c false.
+*/
+
+
+/*!
+ Returns the meta type for keys in the container.
+ */
+QMetaType QMetaAssociation::keyMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->keyMetaType);
+ return QMetaType();
+}
+
+/*!
+ Returns the meta type for mapped values in the container.
+ */
+QMetaType QMetaAssociation::mappedMetaType() const
+{
+ if (auto iface = d())
+ return QMetaType(iface->mappedMetaType);
+ return QMetaType();
+}
+
+QT_END_NAMESPACE