summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-09-10 18:23:23 +0200
committerUlf Hermann <ulf.hermann@qt.io>2020-09-15 15:55:46 +0200
commit1162b4bfc9149ef50bb39b15ecba5ac6ba158290 (patch)
tree4ae0467d645b2bc7ca5e48823c4452a12733c711
parentd423fe985137be1283c0998f54b6ba307a8cf923 (diff)
Add a QMetaAssociation
This requires refactoring of QMetaSequence, as they share a lot of common functionality. QMetaAssociation provides a low level interface to an associative container. Task-number: QTBUG-81716 Change-Id: I273e00abd82f1549ba8803c323d82aa3a2d12ded Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/corelib/global/qcontainerinfo.h122
-rw-r--r--src/corelib/kernel/qmetacontainer.cpp172
-rw-r--r--src/corelib/kernel/qmetacontainer.h1005
-rw-r--r--tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp313
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp2
5 files changed, 1284 insertions, 330 deletions
diff --git a/src/corelib/global/qcontainerinfo.h b/src/corelib/global/qcontainerinfo.h
index c6ee9328ec..e0025fcef0 100644
--- a/src/corelib/global/qcontainerinfo.h
+++ b/src/corelib/global/qcontainerinfo.h
@@ -52,6 +52,12 @@ template<typename C>
using value_type = typename C::value_type;
template<typename C>
+using key_type = typename C::key_type;
+
+template<typename C>
+using mapped_type = typename C::mapped_type;
+
+template<typename C>
using iterator = typename C::iterator;
template<typename C>
@@ -62,6 +68,21 @@ QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wunused-const-variable")
template<typename C, typename = void>
+constexpr bool has_value_type_v = false;
+template<typename C>
+constexpr bool has_value_type_v<C, std::void_t<value_type<C>>> = true;
+
+template<typename C, typename = void>
+constexpr bool has_key_type_v = false;
+template<typename C>
+constexpr bool has_key_type_v<C, std::void_t<key_type<C>>> = true;
+
+template<typename C, typename = void>
+constexpr bool has_mapped_type_v = false;
+template<typename C>
+constexpr bool has_mapped_type_v<C, std::void_t<mapped_type<C>>> = true;
+
+template<typename C, typename = void>
constexpr bool has_size_v = false;
template<typename C>
constexpr bool has_size_v<C, std::void_t<decltype(C().size())>> = true;
@@ -72,9 +93,14 @@ template<typename C>
constexpr bool has_clear_v<C, std::void_t<decltype(C().clear())>> = true;
template<typename, typename = void>
-constexpr bool has_at_v = false;
+constexpr bool has_at_index_v = false;
+template<typename C>
+constexpr bool has_at_index_v<C, std::void_t<decltype(C().at(0))>> = true;
+
+template<typename, typename = void>
+constexpr bool has_at_key_v = false;
template<typename C>
-constexpr bool has_at_v<C, std::void_t<decltype(C().at(0))>> = true;
+constexpr bool has_at_key_v<C, std::void_t<decltype(C().at(key_type<C>()))>> = true;
template<typename, typename = void>
constexpr bool can_get_at_index_v = false;
@@ -122,19 +148,19 @@ template<typename C>
constexpr bool has_const_iterator_v<C, std::void_t<const_iterator<C>>> = true;
template<typename, typename = void>
-constexpr bool can_get_at_iterator_v = false;
+constexpr bool can_set_value_at_iterator_v = false;
template<typename C>
-constexpr bool can_get_at_iterator_v<C, std::void_t<value_type<C>(decltype(*C().begin()))>> = true;
+constexpr bool can_set_value_at_iterator_v<C, std::void_t<decltype(*C().begin() = value_type<C>())>> = true;
template<typename, typename = void>
-constexpr bool can_set_at_iterator_v = false;
+constexpr bool can_set_mapped_at_iterator_v = false;
template<typename C>
-constexpr bool can_set_at_iterator_v<C, std::void_t<decltype(*C().begin() = value_type<C>())>> = true;
+constexpr bool can_set_mapped_at_iterator_v<C, std::void_t<decltype(*C().begin() = mapped_type<C>())>> = true;
template<typename, typename = void>
-constexpr bool can_insert_at_iterator_v = false;
+constexpr bool can_insert_value_at_iterator_v = false;
template<typename C>
-constexpr bool can_insert_at_iterator_v<C, std::void_t<decltype(C().insert(C().begin(), value_type<C>()))>> = true;
+constexpr bool can_insert_value_at_iterator_v<C, std::void_t<decltype(C().insert(C().begin(), value_type<C>()))>> = true;
template<typename, typename = void>
constexpr bool can_erase_at_iterator_v = false;
@@ -146,6 +172,86 @@ constexpr bool can_erase_range_at_iterator_v = false;
template<typename C>
constexpr bool can_erase_range_at_iterator_v<C, std::void_t<decltype(C().erase(C().begin(), C().end()))>> = true;
+template<typename, typename = void>
+constexpr bool can_get_at_key_v = false;
+template<typename C>
+constexpr bool can_get_at_key_v<C, std::void_t<mapped_type<C>(decltype(C()[key_type<C>()]))>> = true;
+
+template<typename, typename = void>
+constexpr bool can_set_at_key_v = false;
+template<typename C>
+constexpr bool can_set_at_key_v<C, std::void_t<decltype(C()[key_type<C>()] = mapped_type<C>())>> = true;
+
+template<typename, typename = void>
+constexpr bool can_erase_at_key_v = false;
+template<typename C>
+constexpr bool can_erase_at_key_v<C, std::void_t<decltype(C().erase(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+constexpr bool can_remove_at_key_v = false;
+template<typename C>
+constexpr bool can_remove_at_key_v<C, std::void_t<decltype(C().remove(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+constexpr bool can_insert_key_v = false;
+template<typename C>
+constexpr bool can_insert_key_v<C, std::void_t<decltype(C().insert(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+constexpr bool can_insert_pair_v = false;
+template<typename C>
+constexpr bool can_insert_pair_v<C, std::void_t<decltype(C().insert({key_type<C>(), mapped_type<C>()}))>> = true;
+
+template<typename, typename = void>
+constexpr bool can_insert_key_mapped_v = false;
+template<typename C>
+constexpr bool can_insert_key_mapped_v<C, std::void_t<decltype(C().insert(key_type<C>(), mapped_type<C>()))>> = true;
+
+template<typename, typename = void>
+constexpr bool has_contains_v = false;
+template<typename C>
+constexpr bool has_contains_v<C, std::void_t<decltype(bool(C().contains(key_type<C>())))>> = true;
+
+template<typename, typename = void>
+constexpr bool has_find_v = false;
+template<typename C>
+constexpr bool has_find_v<C, std::void_t<decltype(C().find(key_type<C>()))>> = true;
+
+template<typename, typename = void>
+constexpr bool iterator_dereferences_to_value_v = false;
+template<typename C>
+constexpr bool iterator_dereferences_to_value_v<C, std::void_t<decltype(value_type<C>(*C().begin()))>> = true;
+
+template<typename, typename = void>
+constexpr bool iterator_has_key_v = false;
+template<typename C>
+constexpr bool iterator_has_key_v<C, std::void_t<decltype(key_type<C>(C().begin().key()))>> = true;
+
+template<typename, typename = void>
+constexpr bool value_type_has_first_v = false;
+template<typename C>
+constexpr bool value_type_has_first_v<C, std::void_t<decltype(key_type<C>(value_type<C>().first))>> = true;
+
+template<typename, typename = void>
+constexpr bool iterator_dereferences_to_key_v = false;
+template<typename C>
+constexpr bool iterator_dereferences_to_key_v<C, std::void_t<decltype(key_type<C>(*C().begin()))>> = true;
+
+template<typename, typename = void>
+constexpr bool iterator_has_value_v = false;
+template<typename C>
+constexpr bool iterator_has_value_v<C, std::void_t<decltype(mapped_type<C>(C().begin().value()))>> = true;
+
+template<typename, typename = void>
+constexpr bool value_type_has_second_v = false;
+template<typename C>
+constexpr bool value_type_has_second_v<C, std::void_t<decltype(mapped_type<C>(value_type<C>().second))>> = true;
+
+template<typename, typename = void>
+constexpr bool iterator_dereferences_to_mapped_v = false;
+template<typename C>
+constexpr bool iterator_dereferences_to_mapped_v<C, std::void_t<decltype(mapped_type<C>(*C().begin()))>> = true;
+
QT_WARNING_POP
}
diff --git a/src/corelib/kernel/qmetacontainer.cpp b/src/corelib/kernel/qmetacontainer.cpp
index 9382909092..c1a752bc1b 100644
--- a/src/corelib/kernel/qmetacontainer.cpp
+++ b/src/corelib/kernel/qmetacontainer.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qmetacontainer.h"
+#include "qmetatype.h"
QT_BEGIN_NAMESPACE
@@ -80,7 +81,7 @@ QT_BEGIN_NAMESPACE
QMetaSequence assumes that const and non-const iterators for the same
container have the same iterator traits.
*/
-bool QMetaSequence::hasInputIterator() const
+bool QMetaContainer::hasInputIterator() const
{
if (!d_ptr)
return false;
@@ -97,7 +98,7 @@ bool QMetaSequence::hasInputIterator() const
QMetaSequence assumes that const and non-const iterators for the same
container have the same iterator traits.
*/
-bool QMetaSequence::hasForwardIterator() const
+bool QMetaContainer::hasForwardIterator() const
{
if (!d_ptr)
return false;
@@ -113,7 +114,7 @@ bool QMetaSequence::hasForwardIterator() const
QMetaSequence assumes that const and non-const iterators for the same
container have the same iterator traits.
*/
-bool QMetaSequence::hasBidirectionalIterator() const
+bool QMetaContainer::hasBidirectionalIterator() const
{
if (!d_ptr)
return false;
@@ -128,7 +129,7 @@ bool QMetaSequence::hasBidirectionalIterator() const
QMetaSequence assumes that const and non-const iterators for the same
container have the same iterator traits.
*/
-bool QMetaSequence::hasRandomAccessIterator() const
+bool QMetaContainer::hasRandomAccessIterator() const
{
if (!d_ptr)
return false;
@@ -140,7 +141,9 @@ bool QMetaSequence::hasRandomAccessIterator() const
*/
QMetaType QMetaSequence::valueMetaType() const
{
- return d_ptr ? d_ptr->valueMetaType : QMetaType();
+ if (auto iface = d())
+ return QMetaType(iface->valueMetaType);
+ return QMetaType();
}
/*!
@@ -156,10 +159,10 @@ QMetaType QMetaSequence::valueMetaType() const
*/
bool QMetaSequence::isSortable() const
{
- if (d_ptr) {
- return (d_ptr->addRemoveCapabilities
+ if (auto iface = d()) {
+ return (iface->addRemoveCapabilities
& (QtMetaContainerPrivate::CanAddAtBegin | QtMetaContainerPrivate::CanAddAtEnd))
- && (d_ptr->addRemoveCapabilities
+ && (iface->addRemoveCapabilities
& (QtMetaContainerPrivate::CanRemoveAtBegin
| QtMetaContainerPrivate::CanRemoveAtEnd));
}
@@ -174,9 +177,9 @@ bool QMetaSequence::isSortable() const
*/
bool QMetaSequence::canAddValueAtBegin() const
{
- if (d_ptr) {
- return d_ptr->addValueFn
- && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtBegin;
}
return false;
}
@@ -190,7 +193,7 @@ bool QMetaSequence::canAddValueAtBegin() const
void QMetaSequence::addValueAtBegin(void *container, const void *value) const
{
if (canAddValueAtBegin())
- d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
}
/*!
@@ -201,9 +204,9 @@ void QMetaSequence::addValueAtBegin(void *container, const void *value) const
*/
bool QMetaSequence::canRemoveValueAtBegin() const
{
- if (d_ptr) {
- return d_ptr->removeValueFn
- && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtBegin;
}
return false;
}
@@ -217,7 +220,7 @@ bool QMetaSequence::canRemoveValueAtBegin() const
void QMetaSequence::removeValueAtBegin(void *container) const
{
if (canRemoveValueAtBegin())
- d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtBegin);
}
/*!
@@ -228,9 +231,9 @@ void QMetaSequence::removeValueAtBegin(void *container) const
*/
bool QMetaSequence::canAddValueAtEnd() const
{
- if (d_ptr) {
- return d_ptr->addValueFn
- && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
+ if (auto iface = d()) {
+ return iface->addValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanAddAtEnd;
}
return false;
}
@@ -244,7 +247,7 @@ bool QMetaSequence::canAddValueAtEnd() const
void QMetaSequence::addValueAtEnd(void *container, const void *value) const
{
if (canAddValueAtEnd())
- d_ptr->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+ d()->addValueFn(container, value, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
}
/*!
@@ -255,9 +258,9 @@ void QMetaSequence::addValueAtEnd(void *container, const void *value) const
*/
bool QMetaSequence::canRemoveValueAtEnd() const
{
- if (d_ptr) {
- return d_ptr->removeValueFn
- && d_ptr->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
+ if (auto iface = d()) {
+ return iface->removeValueFn
+ && iface->addRemoveCapabilities & QtMetaContainerPrivate::CanRemoveAtEnd;
}
return false;
}
@@ -271,7 +274,7 @@ bool QMetaSequence::canRemoveValueAtEnd() const
void QMetaSequence::removeValueAtEnd(void *container) const
{
if (canRemoveValueAtEnd())
- d_ptr->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
+ d()->removeValueFn(container, QtMetaContainerPrivate::QMetaSequenceInterface::AtEnd);
}
/*!
@@ -280,7 +283,7 @@ void QMetaSequence::removeValueAtEnd(void *container) const
\sa size()
*/
-bool QMetaSequence::hasSize() const
+bool QMetaContainer::hasSize() const
{
return d_ptr && d_ptr->sizeFn;
}
@@ -291,7 +294,7 @@ bool QMetaSequence::hasSize() const
\sa hasSize()
*/
-qsizetype QMetaSequence::size(const void *container) const
+qsizetype QMetaContainer::size(const void *container) const
{
return hasSize() ? d_ptr->sizeFn(container) : -1;
}
@@ -301,7 +304,7 @@ qsizetype QMetaSequence::size(const void *container) const
\sa clear()
*/
-bool QMetaSequence::canClear() const
+bool QMetaContainer::canClear() const
{
return d_ptr && d_ptr->clearFn;
}
@@ -311,7 +314,7 @@ bool QMetaSequence::canClear() const
\sa canClear()
*/
-void QMetaSequence::clear(void *container) const
+void QMetaContainer::clear(void *container) const
{
if (canClear())
d_ptr->clearFn(container);
@@ -325,7 +328,9 @@ void QMetaSequence::clear(void *container) const
*/
bool QMetaSequence::canGetValueAtIndex() const
{
- return d_ptr && d_ptr->valueAtIndexFn;
+ if (auto iface = d())
+ return iface->valueAtIndexFn;
+ return false;
}
/*!
@@ -337,7 +342,7 @@ bool QMetaSequence::canGetValueAtIndex() const
void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *result) const
{
if (canGetValueAtIndex())
- d_ptr->valueAtIndexFn(container, index, result);
+ d()->valueAtIndexFn(container, index, result);
}
/*!
@@ -348,7 +353,9 @@ void QMetaSequence::valueAtIndex(const void *container, qsizetype index, void *r
*/
bool QMetaSequence::canSetValueAtIndex() const
{
- return d_ptr && d_ptr->setValueAtIndexFn;
+ if (auto iface = d())
+ return iface->setValueAtIndexFn;
+ return false;
}
/*!
@@ -360,7 +367,7 @@ bool QMetaSequence::canSetValueAtIndex() const
void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void *value) const
{
if (canSetValueAtIndex())
- d_ptr->setValueAtIndexFn(container, index, value);
+ d()->setValueAtIndexFn(container, index, value);
}
/*!
@@ -371,7 +378,9 @@ void QMetaSequence::setValueAtIndex(void *container, qsizetype index, const void
*/
bool QMetaSequence::canAddValue() const
{
- return d_ptr && d_ptr->addValueFn;
+ if (auto iface = d())
+ return iface->addValueFn;
+ return false;
}
/*!
@@ -390,7 +399,7 @@ bool QMetaSequence::canAddValue() const
void QMetaSequence::addValue(void *container, const void *value) const
{
if (canAddValue()) {
- d_ptr->addValueFn(container, value,
+ d()->addValueFn(container, value,
QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
}
}
@@ -403,7 +412,9 @@ void QMetaSequence::addValue(void *container, const void *value) const
*/
bool QMetaSequence::canRemoveValue() const
{
- return d_ptr && d_ptr->removeValueFn;
+ if (auto iface = d())
+ return iface->removeValueFn;
+ return false;
}
/*!
@@ -420,7 +431,7 @@ bool QMetaSequence::canRemoveValue() const
void QMetaSequence::removeValue(void *container) const
{
if (canRemoveValue()) {
- d_ptr->removeValueFn(container,
+ d()->removeValueFn(container,
QtMetaContainerPrivate::QMetaSequenceInterface::Unspecified);
}
}
@@ -432,7 +443,7 @@ void QMetaSequence::removeValue(void *container) const
\sa begin(), end(), destroyIterator(), compareIterator(), diffIterator(),
advanceIterator(), copyIterator()
*/
-bool QMetaSequence::hasIterator() const
+bool QMetaContainer::hasIterator() const
{
if (!d_ptr || !d_ptr->createIteratorFn)
return false;
@@ -453,7 +464,7 @@ bool QMetaSequence::hasIterator() const
\sa end(), constBegin(), constEnd(), destroyIterator()
*/
-void *QMetaSequence::begin(void *container) const
+void *QMetaContainer::begin(void *container) const
{
return hasIterator()
? d_ptr->createIteratorFn(
@@ -470,7 +481,7 @@ void *QMetaSequence::begin(void *container) const
\sa hasIterator(), end(), constBegin(), constEnd(), destroyIterator()
*/
-void *QMetaSequence::end(void *container) const
+void *QMetaContainer::end(void *container) const
{
return hasIterator()
? d_ptr->createIteratorFn(
@@ -484,7 +495,7 @@ void *QMetaSequence::end(void *container) const
\sa begin(), end(), destroyConstIterator()
*/
-void QMetaSequence::destroyIterator(const void *iterator) const
+void QMetaContainer::destroyIterator(const void *iterator) const
{
if (hasIterator())
d_ptr->destroyIteratorFn(iterator);
@@ -497,7 +508,7 @@ void QMetaSequence::destroyIterator(const void *iterator) const
\sa begin(), end()
*/
-bool QMetaSequence::compareIterator(const void *i, const void *j) const
+bool QMetaContainer::compareIterator(const void *i, const void *j) const
{
return hasIterator() ? d_ptr->compareIteratorFn(i, j) : false;
}
@@ -508,7 +519,7 @@ bool QMetaSequence::compareIterator(const void *i, const void *j) const
\sa begin(), end()
*/
-void QMetaSequence::copyIterator(void *target, const void *source) const
+void QMetaContainer::copyIterator(void *target, const void *source) const
{
if (hasIterator())
d_ptr->copyIteratorFn(target, source);
@@ -522,7 +533,7 @@ void QMetaSequence::copyIterator(void *target, const void *source) const
\sa begin(), end()
*/
-void QMetaSequence::advanceIterator(void *iterator, qsizetype step) const
+void QMetaContainer::advanceIterator(void *iterator, qsizetype step) const
{
if (hasIterator())
d_ptr->advanceIteratorFn(iterator, step);
@@ -536,7 +547,7 @@ void QMetaSequence::advanceIterator(void *iterator, qsizetype step) const
\sa begin(), end()
*/
-qsizetype QMetaSequence::diffIterator(const void *i, const void *j) const
+qsizetype QMetaContainer::diffIterator(const void *i, const void *j) const
{
return hasIterator() ? d_ptr->diffIteratorFn(i, j) : 0;
}
@@ -549,7 +560,9 @@ qsizetype QMetaSequence::diffIterator(const void *i, const void *j) const
*/
bool QMetaSequence::canGetValueAtIterator() const
{
- return d_ptr && d_ptr->valueAtIteratorFn;
+ if (auto iface = d())
+ return iface->valueAtIteratorFn;
+ return false;
}
/*!
@@ -561,7 +574,7 @@ bool QMetaSequence::canGetValueAtIterator() const
void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
{
if (canGetValueAtIterator())
- d_ptr->valueAtIteratorFn(iterator, result);
+ d()->valueAtIteratorFn(iterator, result);
}
/*!
@@ -572,7 +585,9 @@ void QMetaSequence::valueAtIterator(const void *iterator, void *result) const
*/
bool QMetaSequence::canSetValueAtIterator() const
{
- return d_ptr && d_ptr->setValueAtIteratorFn;
+ if (auto iface = d())
+ return iface->setValueAtIteratorFn;
+ return false;
}
/*!
@@ -584,7 +599,7 @@ bool QMetaSequence::canSetValueAtIterator() const
void QMetaSequence::setValueAtIterator(const void *iterator, const void *value) const
{
if (canSetValueAtIterator())
- d_ptr->setValueAtIteratorFn(iterator, value);
+ d()->setValueAtIteratorFn(iterator, value);
}
/*!
@@ -595,7 +610,9 @@ void QMetaSequence::setValueAtIterator(const void *iterator, const void *value)
*/
bool QMetaSequence::canInsertValueAtIterator() const
{
- return d_ptr && d_ptr->insertValueAtIteratorFn;
+ if (auto iface = d())
+ return iface->insertValueAtIteratorFn;
+ return false;
}
/*!
@@ -614,7 +631,7 @@ void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
const void *value) const
{
if (canInsertValueAtIterator())
- d_ptr->insertValueAtIteratorFn(container, iterator, value);
+ d()->insertValueAtIteratorFn(container, iterator, value);
}
/*!
@@ -625,7 +642,9 @@ void QMetaSequence::insertValueAtIterator(void *container, const void *iterator,
*/
bool QMetaSequence::canEraseValueAtIterator() const
{
- return d_ptr && d_ptr->eraseValueAtIteratorFn;
+ if (auto iface = d())
+ return iface->eraseValueAtIteratorFn;
+ return false;
}
/*!
@@ -637,7 +656,7 @@ bool QMetaSequence::canEraseValueAtIterator() const
void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator) const
{
if (canEraseValueAtIterator())
- d_ptr->eraseValueAtIteratorFn(container, iterator);
+ d()->eraseValueAtIteratorFn(container, iterator);
}
/*!
@@ -646,8 +665,8 @@ void QMetaSequence::eraseValueAtIterator(void *container, const void *iterator)
*/
bool QMetaSequence::canEraseRangeAtIterator() const
{
- if (d_ptr)
- return d_ptr->eraseRangeAtIteratorFn;
+ if (auto iface = d())
+ return iface->eraseRangeAtIteratorFn;
return false;
}
@@ -661,7 +680,7 @@ void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
const void *iterator2) const
{
if (canEraseRangeAtIterator())
- d_ptr->eraseRangeAtIteratorFn(container, iterator1, iterator2);
+ d()->eraseRangeAtIteratorFn(container, iterator1, iterator2);
}
/*!
@@ -672,7 +691,7 @@ void QMetaSequence::eraseRangeAtIterator(void *container, const void *iterator1,
compareConstIterator(), diffConstIterator(), advanceConstIterator(),
copyConstIterator()
*/
-bool QMetaSequence::hasConstIterator() const
+bool QMetaContainer::hasConstIterator() const
{
if (!d_ptr || !d_ptr->createConstIteratorFn)
return false;
@@ -693,7 +712,7 @@ bool QMetaSequence::hasConstIterator() const
\sa constEnd(), begin(), end(), destroyConstIterator()
*/
-void *QMetaSequence::constBegin(const void *container) const
+void *QMetaContainer::constBegin(const void *container) const
{
return hasConstIterator()
? d_ptr->createConstIteratorFn(
@@ -710,7 +729,7 @@ void *QMetaSequence::constBegin(const void *container) const
\sa constBegin(), begin(), end(), destroyConstIterator()
*/
-void *QMetaSequence::constEnd(const void *container) const
+void *QMetaContainer::constEnd(const void *container) const
{
return hasConstIterator()
? d_ptr->createConstIteratorFn(
@@ -724,7 +743,7 @@ void *QMetaSequence::constEnd(const void *container) const
\sa constBegin(), constEnd(), destroyIterator()
*/
-void QMetaSequence::destroyConstIterator(const void *iterator) const
+void QMetaContainer::destroyConstIterator(const void *iterator) const
{
if (hasConstIterator())
d_ptr->destroyConstIteratorFn(iterator);
@@ -737,7 +756,7 @@ void QMetaSequence::destroyConstIterator(const void *iterator) const
\sa constBegin(), constEnd()
*/
-bool QMetaSequence::compareConstIterator(const void *i, const void *j) const
+bool QMetaContainer::compareConstIterator(const void *i, const void *j) const
{
return hasConstIterator() ? d_ptr->compareConstIteratorFn(i, j) : false;
}
@@ -748,7 +767,7 @@ bool QMetaSequence::compareConstIterator(const void *i, const void *j) const
\sa constBegin(), constEnd()
*/
-void QMetaSequence::copyConstIterator(void *target, const void *source) const
+void QMetaContainer::copyConstIterator(void *target, const void *source) const
{
if (hasConstIterator())
d_ptr->copyConstIteratorFn(target, source);
@@ -762,7 +781,7 @@ void QMetaSequence::copyConstIterator(void *target, const void *source) const
\sa constBegin(), constEnd()
*/
-void QMetaSequence::advanceConstIterator(void *iterator, qsizetype step) const
+void QMetaContainer::advanceConstIterator(void *iterator, qsizetype step) const
{
if (hasConstIterator())
d_ptr->advanceConstIteratorFn(iterator, step);
@@ -776,7 +795,7 @@ void QMetaSequence::advanceConstIterator(void *iterator, qsizetype step) const
\sa constBegin(), constEnd()
*/
-qsizetype QMetaSequence::diffConstIterator(const void *i, const void *j) const
+qsizetype QMetaContainer::diffConstIterator(const void *i, const void *j) const
{
return hasConstIterator() ? d_ptr->diffConstIteratorFn(i, j) : 0;
}
@@ -789,7 +808,9 @@ qsizetype QMetaSequence::diffConstIterator(const void *i, const void *j) const
*/
bool QMetaSequence::canGetValueAtConstIterator() const
{
- return d_ptr && d_ptr->valueAtConstIteratorFn;
+ if (auto iface = d())
+ return iface->valueAtConstIteratorFn;
+ return false;
}
/*!
@@ -801,7 +822,7 @@ bool QMetaSequence::canGetValueAtConstIterator() const
void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) const
{
if (canGetValueAtConstIterator())
- d_ptr->valueAtConstIteratorFn(iterator, result);
+ d()->valueAtConstIteratorFn(iterator, result);
}
/*!
@@ -822,4 +843,25 @@ void QMetaSequence::valueAtConstIterator(const void *iterator, void *result) con
type than the QMetaSequence \a b, 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
diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h
index 1f7771a0bc..a873bb2106 100644
--- a/src/corelib/kernel/qmetacontainer.h
+++ b/src/corelib/kernel/qmetacontainer.h
@@ -43,10 +43,16 @@
#include <QtCore/qcontainerinfo.h>
#include <QtCore/qflags.h>
#include <QtCore/qglobal.h>
-#include <QtCore/qmetatype.h>
QT_BEGIN_NAMESPACE
+class QMetaType;
+namespace QtPrivate {
+class QMetaTypeInterface;
+template<typename T>
+constexpr QMetaTypeInterface *qMetaTypeInterfaceForType();
+}
+
namespace QtMetaContainerPrivate {
enum IteratorCapability : quint8 {
@@ -68,31 +74,18 @@ enum AddRemoveCapability : quint8 {
Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
-class QMetaSequenceInterface
+class QMetaContainerInterface
{
public:
enum Position : quint8 { AtBegin, AtEnd, Unspecified };
-
- ushort revision;
+ ushort revision = 0;
IteratorCapabilities iteratorCapabilities;
- QMetaType valueMetaType;
- AddRemoveCapabilities addRemoveCapabilities;
using SizeFn = qsizetype(*)(const void *);
SizeFn sizeFn;
using ClearFn = void(*)(void *);
ClearFn clearFn;
- using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
- ValueAtIndexFn valueAtIndexFn;
- using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
- SetValueAtIndexFn setValueAtIndexFn;
-
- using AddValueFn = void(*)(void *, const void *, Position);
- AddValueFn addValueFn;
- using RemoveValueFn = void(*)(void *, Position);
- RemoveValueFn removeValueFn;
-
using CreateIteratorFn = void *(*)(void *, Position);
CreateIteratorFn createIteratorFn;
using DestroyIteratorFn = void(*)(const void *);
@@ -105,30 +98,153 @@ public:
AdvanceIteratorFn advanceIteratorFn;
using DiffIteratorFn = qsizetype(*)(const void *, const void *);
DiffIteratorFn diffIteratorFn;
+
+ using CreateConstIteratorFn = void *(*)(const void *, Position);
+ CreateConstIteratorFn createConstIteratorFn;
+ DestroyIteratorFn destroyConstIteratorFn;
+ CompareIteratorFn compareConstIteratorFn;
+ CopyIteratorFn copyConstIteratorFn;
+ AdvanceIteratorFn advanceConstIteratorFn;
+ DiffIteratorFn diffConstIteratorFn;
+
+ QMetaContainerInterface() = default;
+
+ template<typename MetaContainer>
+ QMetaContainerInterface(const MetaContainer &)
+ : iteratorCapabilities(MetaContainer::getIteratorCapabilities())
+ , sizeFn(MetaContainer::getSizeFn())
+ , clearFn(MetaContainer::getClearFn())
+ , createIteratorFn(MetaContainer::getCreateIteratorFn())
+ , destroyIteratorFn(MetaContainer::getDestroyIteratorFn())
+ , compareIteratorFn(MetaContainer::getCompareIteratorFn())
+ , copyIteratorFn(MetaContainer::getCopyIteratorFn())
+ , advanceIteratorFn(MetaContainer::getAdvanceIteratorFn())
+ , diffIteratorFn(MetaContainer::getDiffIteratorFn())
+ , createConstIteratorFn(MetaContainer::getCreateConstIteratorFn())
+ , destroyConstIteratorFn(MetaContainer::getDestroyConstIteratorFn())
+ , compareConstIteratorFn(MetaContainer::getCompareConstIteratorFn())
+ , copyConstIteratorFn(MetaContainer::getCopyConstIteratorFn())
+ , advanceConstIteratorFn(MetaContainer::getAdvanceConstIteratorFn())
+ , diffConstIteratorFn(MetaContainer::getDiffConstIteratorFn())
+ {}
+};
+
+class QMetaSequenceInterface : public QMetaContainerInterface
+{
+public:
+ QtPrivate::QMetaTypeInterface *valueMetaType;
+ AddRemoveCapabilities addRemoveCapabilities;
+
+ using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
+ ValueAtIndexFn valueAtIndexFn;
+ using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
+ SetValueAtIndexFn setValueAtIndexFn;
+
+ using AddValueFn = void(*)(void *, const void *, Position);
+ AddValueFn addValueFn;
+ using RemoveValueFn = void(*)(void *, Position);
+ RemoveValueFn removeValueFn;
+
using ValueAtIteratorFn = void(*)(const void *, void *);
ValueAtIteratorFn valueAtIteratorFn;
using SetValueAtIteratorFn = void(*)(const void *, const void *);
SetValueAtIteratorFn setValueAtIteratorFn;
using InsertValueAtIteratorFn = void(*)(void *, const void *, const void *);
InsertValueAtIteratorFn insertValueAtIteratorFn;
+
+ ValueAtIteratorFn valueAtConstIteratorFn;
+
using EraseValueAtIteratorFn = void(*)(void *, const void *);
EraseValueAtIteratorFn eraseValueAtIteratorFn;
+
using EraseRangeAtIteratorFn = void(*)(void *, const void *, const void *);
EraseRangeAtIteratorFn eraseRangeAtIteratorFn;
- using CreateConstIteratorFn = void *(*)(const void *, Position);
- CreateConstIteratorFn createConstIteratorFn;
- DestroyIteratorFn destroyConstIteratorFn;
- CompareIteratorFn compareConstIteratorFn;
- CopyIteratorFn copyConstIteratorFn;
- AdvanceIteratorFn advanceConstIteratorFn;
- DiffIteratorFn diffConstIteratorFn;
- ValueAtIteratorFn valueAtConstIteratorFn;
+ QMetaSequenceInterface() = default;
+
+ template<typename MetaSequence>
+ QMetaSequenceInterface(const MetaSequence &m)
+ : QMetaContainerInterface(m)
+ , valueMetaType(MetaSequence::getValueMetaType())
+ , addRemoveCapabilities(MetaSequence::getAddRemoveCapabilities())
+ , valueAtIndexFn(MetaSequence::getValueAtIndexFn())
+ , setValueAtIndexFn(MetaSequence::getSetValueAtIndexFn())
+ , addValueFn(MetaSequence::getAddValueFn())
+ , removeValueFn(MetaSequence::getRemoveValueFn())
+ , valueAtIteratorFn(MetaSequence::getValueAtIteratorFn())
+ , setValueAtIteratorFn(MetaSequence::getSetValueAtIteratorFn())
+ , insertValueAtIteratorFn(MetaSequence::getInsertValueAtIteratorFn())
+ , valueAtConstIteratorFn(MetaSequence::getValueAtConstIteratorFn())
+ , eraseValueAtIteratorFn(MetaSequence::getEraseValueAtIteratorFn())
+ , eraseRangeAtIteratorFn(MetaSequence::getEraseRangeAtIteratorFn())
+ {}
+};
+
+class QMetaAssociationInterface : public QMetaContainerInterface
+{
+public:
+ QtPrivate::QMetaTypeInterface *keyMetaType;
+ QtPrivate::QMetaTypeInterface *mappedMetaType;
+
+ using InsertKeyFn = void(*)(void *, const void *);
+ InsertKeyFn insertKeyFn;
+ using RemoveKeyFn = void(*)(void *, const void *);
+ RemoveKeyFn removeKeyFn;
+ using ContainsKeyFn = bool(*)(const void *, const void *);
+ ContainsKeyFn containsKeyFn;
+
+ using MappedAtKeyFn = void(*)(const void *, const void *, void *);
+ MappedAtKeyFn mappedAtKeyFn;
+ using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
+ SetMappedAtKeyFn setMappedAtKeyFn;
+
+ using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
+ CreateIteratorAtKeyFn createIteratorAtKeyFn;
+ using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
+ CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
+
+ using KeyAtIteratorFn = void(*)(const void *, void *);
+ KeyAtIteratorFn keyAtIteratorFn;
+ KeyAtIteratorFn keyAtConstIteratorFn;
+
+ using MappedAtIteratorFn = void(*)(const void *, void *);
+ MappedAtIteratorFn mappedAtIteratorFn;
+ MappedAtIteratorFn mappedAtConstIteratorFn;
+
+ using SetMappedAtIteratorFn = void(*)(const void *, const void *);
+ SetMappedAtIteratorFn setMappedAtIteratorFn;
+
+ using EraseKeyAtIteratorFn = void(*)(void *, const void *);
+ EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
+
+ QMetaAssociationInterface() = default;
+
+ template<typename MetaAssociation>
+ QMetaAssociationInterface(const MetaAssociation &m)
+ : QMetaContainerInterface(m)
+ , keyMetaType(MetaAssociation::getKeyMetaType())
+ , mappedMetaType(MetaAssociation::getMappedMetaType())
+ , insertKeyFn(MetaAssociation::getInsertKeyFn())
+ , removeKeyFn(MetaAssociation::getRemoveKeyFn())
+ , containsKeyFn(MetaAssociation::getContainsKeyFn())
+ , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
+ , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
+ , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
+ , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
+ , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
+ , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
+ , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
+ , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
+ , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
+ , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
+ {}
};
template<typename C>
-class QMetaSequenceForContainer
+class QMetaContainerForContainer
{
+ friend QMetaContainerInterface;
+
template <typename Iterator>
static constexpr IteratorCapabilities capabilitiesForIterator()
{
@@ -155,46 +271,230 @@ class QMetaSequenceForContainer
return {};
}
- static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
+ static constexpr QMetaContainerInterface::SizeFn getSizeFn()
{
- AddRemoveCapabilities caps;
- if constexpr (QContainerTraits::has_push_back_v<C>)
- caps |= CanAddAtEnd;
- if constexpr (QContainerTraits::has_pop_back_v<C>)
- caps |= CanRemoveAtEnd;
- if constexpr (QContainerTraits::has_push_front_v<C>)
- caps |= CanAddAtBegin;
- if constexpr (QContainerTraits::has_pop_front_v<C>)
- caps |= CanRemoveAtBegin;
- return caps;
+ if constexpr (QContainerTraits::has_size_v<C>) {
+ return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
+ } else {
+ return nullptr;
+ }
}
- static constexpr QMetaType getValueMetaType()
+ static constexpr QMetaContainerInterface::ClearFn getClearFn()
{
- return QMetaType::fromType<typename C::value_type>();
+ if constexpr (QContainerTraits::has_clear_v<C>) {
+ return [](void *c) { return static_cast<C *>(c)->clear(); };
+ } else {
+ return nullptr;
+ }
}
- static constexpr QMetaSequenceInterface::SizeFn getSizeFn()
+ static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
{
- if constexpr (QContainerTraits::has_size_v<C>) {
- return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, QMetaContainerInterface::Position p) -> void* {
+ using Iterator = QContainerTraits::iterator<C>;
+ switch (p) {
+ case QMetaContainerInterface::Unspecified:
+ return new Iterator;
+ case QMetaContainerInterface::AtBegin:
+ return new Iterator(static_cast<C *>(c)->begin());
+ break;
+ case QMetaContainerInterface::AtEnd:
+ return new Iterator(static_cast<C *>(c)->end());
+ break;
+ }
+ return nullptr;
+ };
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::ClearFn getClearFn()
+ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
{
- if constexpr (QContainerTraits::has_clear_v<C>) {
- return [](void *c) { return static_cast<C *>(c)->clear(); };
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i) {
+ using Iterator = QContainerTraits::iterator<C>;
+ delete static_cast<const Iterator *>(i);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *j) {
+ using Iterator = QContainerTraits::iterator<C>;
+ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ };
} else {
return nullptr;
}
}
+ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *i, const void *j) {
+ using Iterator = QContainerTraits::iterator<C>;
+ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *i, qsizetype step) {
+ std::advance(*static_cast<QContainerTraits::iterator<C> *>(i), step);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *j) -> qsizetype {
+ return std::distance(*static_cast<const QContainerTraits::iterator<C> *>(j),
+ *static_cast<const QContainerTraits::iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](const void *c, QMetaContainerInterface::Position p) -> void* {
+ using Iterator = QContainerTraits::const_iterator<C>;
+ switch (p) {
+ case QMetaContainerInterface::Unspecified:
+ return new Iterator;
+ case QMetaContainerInterface::AtBegin:
+ return new Iterator(static_cast<const C *>(c)->begin());
+ case QMetaContainerInterface::AtEnd:
+ return new Iterator(static_cast<const C *>(c)->end());
+ }
+ return nullptr;
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](const void *i) {
+ using Iterator = QContainerTraits::const_iterator<C>;
+ delete static_cast<const Iterator *>(i);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](const void *i, const void *j) {
+ using Iterator = QContainerTraits::const_iterator<C>;
+ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](void *i, const void *j) {
+ using Iterator = QContainerTraits::const_iterator<C>;
+ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](void *i, qsizetype step) {
+ std::advance(*static_cast<QContainerTraits::const_iterator<C> *>(i), step);
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_const_iterator_v<C>) {
+ return [](const void *i, const void *j) -> qsizetype {
+ return std::distance(*static_cast<const QContainerTraits::const_iterator<C> *>(j),
+ *static_cast<const QContainerTraits::const_iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+
+protected:
+
+ template<typename EraseFn>
+ static constexpr EraseFn getEraseAtIteratorFn()
+ {
+ if constexpr (QContainerTraits::has_iterator_v<C>
+ && QContainerTraits::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i));
+ };
+ } else {
+ return nullptr;
+ }
+ }
+};
+
+template<typename C>
+class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
+{
+ friend QMetaSequenceInterface;
+
+ static constexpr QtPrivate::QMetaTypeInterface *getValueMetaType()
+ {
+ if constexpr (QContainerTraits::has_value_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
+ else
+ return nullptr;
+ }
+
+ static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
+ {
+ AddRemoveCapabilities caps;
+ if constexpr (QContainerTraits::has_push_back_v<C>)
+ caps |= CanAddAtEnd;
+ if constexpr (QContainerTraits::has_pop_back_v<C>)
+ caps |= CanRemoveAtEnd;
+ if constexpr (QContainerTraits::has_push_front_v<C>)
+ caps |= CanAddAtBegin;
+ if constexpr (QContainerTraits::has_pop_front_v<C>)
+ caps |= CanRemoveAtBegin;
+ return caps;
+ }
+
static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
{
- if constexpr (QContainerTraits::has_at_v<C>) {
+ if constexpr (QContainerTraits::has_at_index_v<C>) {
return [](const void *c, qsizetype i, void *r) {
*static_cast<QContainerTraits::value_type<C> *>(r)
= static_cast<const C *>(c)->at(i);
@@ -316,279 +616,319 @@ class QMetaSequenceForContainer
}
}
- static constexpr QMetaSequenceInterface::CreateIteratorFn getCreateIteratorFn()
+ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *c, QMetaSequenceInterface::Position p) -> void* {
- using Iterator = QContainerTraits::iterator<C>;
- switch (p) {
- case QMetaSequenceInterface::AtBegin:
- case QMetaSequenceInterface::Unspecified:
- return new Iterator(static_cast<C *>(c)->begin());
- break;
- case QMetaSequenceInterface::AtEnd:
- return new Iterator(static_cast<C *>(c)->end());
- break;
- }
- return nullptr;
+ if constexpr (QContainerTraits::has_iterator_v<C>
+ && QContainerTraits::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, void *r) {
+ *static_cast<QContainerTraits::value_type<C> *>(r) =
+ *(*static_cast<const QContainerTraits::iterator<C> *>(i));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyIteratorFn()
+ static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](const void *i) {
- using Iterator = QContainerTraits::iterator<C>;
- delete static_cast<const Iterator *>(i);
+ if constexpr (QContainerTraits::has_iterator_v<C>
+ && QContainerTraits::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *e) {
+ *(*static_cast<const QContainerTraits::iterator<C> *>(i))
+ = *static_cast<const QContainerTraits::value_type<C> *>(e);
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareIteratorFn()
+ static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](const void *i, const void *j) {
- using Iterator = QContainerTraits::iterator<C>;
- return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ if constexpr (QContainerTraits::has_iterator_v<C>
+ && QContainerTraits::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i, const void *e) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerTraits::iterator<C> *>(i),
+ *static_cast<const QContainerTraits::value_type<C> *>(e));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyIteratorFn()
+ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *i, const void *j) {
- using Iterator = QContainerTraits::iterator<C>;
- *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ if constexpr (QContainerTraits::has_const_iterator_v<C>
+ && QContainerTraits::iterator_dereferences_to_value_v<C>) {
+ return [](const void *i, void *r) {
+ *static_cast<QContainerTraits::value_type<C> *>(r) =
+ *(*static_cast<const QContainerTraits::const_iterator<C> *>(i));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceIteratorFn()
+ static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *i, qsizetype step) {
- std::advance(*static_cast<QContainerTraits::iterator<C> *>(i), step);
- };
- } else {
- return nullptr;
- }
+ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
+ QMetaSequenceInterface::EraseValueAtIteratorFn>();
}
- static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffIteratorFn()
+ static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C> && !std::is_const_v<C>) {
- return [](const void *i, const void *j) -> qsizetype {
- return std::distance(*static_cast<const QContainerTraits::iterator<C> *>(j),
- *static_cast<const QContainerTraits::iterator<C> *>(i));
+ if constexpr (QContainerTraits::has_iterator_v<C>
+ && QContainerTraits::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](void *c, const void *i, const void *j) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i),
+ *static_cast<const QContainerTraits::iterator<C> *>(j));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
+public:
+ static QMetaSequenceInterface metaSequence;
+};
+
+template<typename C>
+class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
+{
+ friend QMetaAssociationInterface;
+
+ static constexpr QtPrivate::QMetaTypeInterface *getKeyMetaType()
{
- if constexpr (QContainerTraits::has_iterator_v<C>
- && QContainerTraits::can_get_at_iterator_v<C> && !std::is_const_v<C>) {
- return [](const void *i, void *r) {
- *static_cast<QContainerTraits::value_type<C> *>(r) =
- *(*static_cast<const QContainerTraits::iterator<C> *>(i));
- };
- } else {
+ if constexpr (QContainerTraits::has_key_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
+ else
return nullptr;
- }
}
- static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
+ static constexpr QtPrivate::QMetaTypeInterface *getMappedMetaType()
{
- if constexpr (QContainerTraits::has_iterator_v<C>
- && QContainerTraits::can_set_at_iterator_v<C> && !std::is_const_v<C>) {
- return [](const void *i, const void *e) {
- *(*static_cast<const QContainerTraits::iterator<C> *>(i))
- = *static_cast<const QContainerTraits::value_type<C> *>(e);
- };
- } else {
+ if constexpr (QContainerTraits::has_mapped_type_v<C>)
+ return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
+ else
return nullptr;
- }
}
- static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
+ static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C>
- && QContainerTraits::can_insert_at_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *c, const void *i, const void *e) {
+ if constexpr (QContainerTraits::can_insert_key_v<C>) {
+ return [](void *c, const void *k) {
static_cast<C *>(c)->insert(
- *static_cast<const QContainerTraits::iterator<C> *>(i),
- *static_cast<const QContainerTraits::value_type<C> *>(e));
+ *static_cast<const QContainerTraits::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerTraits::can_insert_pair_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->insert(
+ {*static_cast<const QContainerTraits::key_type<C> *>(k), {}});
+ };
+ } else if constexpr (QContainerTraits::can_insert_key_mapped_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->insert(
+ *static_cast<const QContainerTraits::key_type<C> *>(k), {});
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
+ static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C>
- && QContainerTraits::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *c, const void *i) {
- static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i));
+ if constexpr (QContainerTraits::can_erase_at_key_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerTraits::can_remove_at_key_v<C>) {
+ return [](void *c, const void *k) {
+ static_cast<C *>(c)->remove(*static_cast<const QContainerTraits::key_type<C> *>(k));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
+ static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
{
- if constexpr (QContainerTraits::has_iterator_v<C>
- && QContainerTraits::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
- return [](void *c, const void *i, const void *j) {
- static_cast<C *>(c)->erase(*static_cast<const QContainerTraits::iterator<C> *>(i),
- *static_cast<const QContainerTraits::iterator<C> *>(j));
+ if constexpr (QContainerTraits::has_contains_v<C>) {
+ return [](const void *c, const void *k) {
+ return static_cast<const C *>(c)->contains(
+ *static_cast<const QContainerTraits::key_type<C> *>(k));
+ };
+ } else if (QContainerTraits::has_find_v<C>) {
+ return [](const void *c, const void *k) {
+ const C *container = static_cast<const C *>(c);
+ return container->find(
+ *static_cast<const QContainerTraits::key_type<C> *>(k))
+ != container->end();
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::CreateConstIteratorFn getCreateConstIteratorFn()
+ static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](const void *c, QMetaSequenceInterface::Position p) -> void* {
- using Iterator = QContainerTraits::const_iterator<C>;
- switch (p) {
- case QMetaSequenceInterface::AtBegin:
- case QMetaSequenceInterface::Unspecified:
- return new Iterator(static_cast<const C *>(c)->begin());
- break;
- case QMetaSequenceInterface::AtEnd:
- return new Iterator(static_cast<const C *>(c)->end());
- break;
- }
- return nullptr;
+ if constexpr (QContainerTraits::has_at_key_v<C>) {
+ return [](const void *c, const void *k, void *r) {
+ *static_cast<QContainerTraits::mapped_type<C> *>(r)
+ = static_cast<const C *>(c)->at(
+ *static_cast<const QContainerTraits::key_type<C> *>(k));
+ };
+ } else if constexpr (QContainerTraits::can_get_at_key_v<C>) {
+ return [](const void *c, const void *k, void *r) {
+ *static_cast<QContainerTraits::mapped_type<C> *>(r)
+ = (*static_cast<const C *>(c))[
+ *static_cast<const QContainerTraits::key_type<C> *>(k)];
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyConstIteratorFn()
+ static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](const void *i) {
- using Iterator = QContainerTraits::const_iterator<C>;
- delete static_cast<const Iterator *>(i);
+ if constexpr (QContainerTraits::can_set_at_key_v<C>) {
+ return [](void *c, const void *k, const void *m) {
+ (*static_cast<C *>(c))[*static_cast<const QContainerTraits::key_type<C> *>(k)] =
+ *static_cast<const QContainerTraits::mapped_type<C> *>(m);
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareConstIteratorFn()
+ static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](const void *i, const void *j) {
- using Iterator = QContainerTraits::const_iterator<C>;
- return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
+ if constexpr (QContainerTraits::has_find_v<C>) {
+ return [](void *c, const void *k) -> void* {
+ using Iterator = QContainerTraits::iterator<C>;
+ return new Iterator(static_cast<C *>(c)->find(
+ *static_cast<const QContainerTraits::key_type<C> *>(k)));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyConstIteratorFn()
+ static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](void *i, const void *j) {
+ if constexpr (QContainerTraits::has_find_v<C>) {
+ return [](const void *c, const void *k) -> void* {
using Iterator = QContainerTraits::const_iterator<C>;
- *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
+ return new Iterator(static_cast<const C *>(c)->find(
+ *static_cast<const QContainerTraits::key_type<C> *>(k)));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
+ template<typename Iterator>
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](void *i, qsizetype step) {
- std::advance(*static_cast<QContainerTraits::const_iterator<C> *>(i), step);
+ if constexpr (QContainerTraits::iterator_has_key_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::key_type<C> *>(k)
+ = static_cast<const Iterator *>(i)->key();
+ };
+ } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
+ && QContainerTraits::value_type_has_first_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::key_type<C> *>(k)
+ = (*static_cast<const Iterator *>(i))->first;
+ };
+ } else if constexpr (QContainerTraits::iterator_dereferences_to_key_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::key_type<C> *>(k)
+ = *(*static_cast<const Iterator *>(i));
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffConstIteratorFn()
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>) {
- return [](const void *i, const void *j) -> qsizetype {
- return std::distance(*static_cast<const QContainerTraits::const_iterator<C> *>(j),
- *static_cast<const QContainerTraits::const_iterator<C> *>(i));
+ return keyAtIteratorFn<QContainerTraits::iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
+ {
+ return keyAtIteratorFn<QContainerTraits::const_iterator<C>>();
+ }
+
+ template<typename Iterator>
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
+ {
+ if constexpr (QContainerTraits::iterator_has_value_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::mapped_type<C> *>(k)
+ = static_cast<const Iterator *>(i)->value();
+ };
+ } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
+ && QContainerTraits::value_type_has_second_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::mapped_type<C> *>(k)
+ = (*static_cast<const Iterator *>(i))->second;
+ };
+ } else if constexpr (QContainerTraits::iterator_dereferences_to_mapped_v<C>) {
+ return [](const void *i, void *k) {
+ *static_cast<QContainerTraits::mapped_type<C> *>(k)
+ = *static_cast<const Iterator *>(i);
};
} else {
return nullptr;
}
}
- static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
{
- if constexpr (QContainerTraits::has_const_iterator_v<C>
- && QContainerTraits::can_get_at_iterator_v<C>) {
- return [](const void *i, void *r) {
- *static_cast<QContainerTraits::value_type<C> *>(r) =
- *(*static_cast<const QContainerTraits::const_iterator<C> *>(i));
+ return mappedAtIteratorFn<QContainerTraits::iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
+ {
+ return mappedAtIteratorFn<QContainerTraits::const_iterator<C>>();
+ }
+
+ static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
+ {
+ if constexpr (QContainerTraits::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
+ return [](const void *i, const void *m) {
+ *(*static_cast<const QContainerTraits::iterator<C> *>(i))
+ = *static_cast<const QContainerTraits::mapped_type<C> *>(m);
+ };
+ } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v<C>
+ && QContainerTraits::value_type_has_second_v<C>) {
+ return [](const void *i, const void *m) {
+ (*static_cast<const QContainerTraits::iterator<C> *>(i))->second
+ = *static_cast<const QContainerTraits::mapped_type<C> *>(m);
};
} else {
return nullptr;
}
}
+ static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
+ {
+ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
+ QMetaAssociationInterface::EraseKeyAtIteratorFn>();
+ }
+
public:
- static QMetaSequenceInterface metaSequence;
+ static QMetaAssociationInterface metaAssociation;
};
template<typename C>
-QMetaSequenceInterface QMetaSequenceForContainer<C>::metaSequence = {
- /*.revision=*/ 0,
- /*.iteratorCapabilities=*/ getIteratorCapabilities(),
- /*.valueMetaType=*/ getValueMetaType(),
- /*.addRemoveCapabilities=*/ getAddRemoveCapabilities(),
- /*.sizeFn=*/ getSizeFn(),
- /*.clearFn=*/ getClearFn(),
- /*.valueAtIndexFn=*/ getValueAtIndexFn(),
- /*.setValueAtIndexFn=*/ getSetValueAtIndexFn(),
- /*.addValueFn=*/ getAddValueFn(),
- /*.removeLastValueFn=*/ getRemoveValueFn(),
- /*.createIteratorFn=*/ getCreateIteratorFn(),
- /*.destroyIteratorFn=*/ getDestroyIteratorFn(),
- /*.equalIteratorFn=*/ getCompareIteratorFn(),
- /*.copyIteratorFn=*/ getCopyIteratorFn(),
- /*.advanceIteratorFn=*/ getAdvanceIteratorFn(),
- /*.diffIteratorFn=*/ getDiffIteratorFn(),
- /*.valueAtIteratorFn=*/ getValueAtIteratorFn(),
- /*.setValueAtIteratorFn=*/ getSetValueAtIteratorFn(),
- /*.insertValueAtIteratorFn=*/ getInsertValueAtIteratorFn(),
- /*.eraseValueAtIteratorFn=*/ getEraseValueAtIteratorFn(),
- /*.eraseRangeAtIteratorFn=*/ getEraseRangeAtIteratorFn(),
- /*.createConstIteratorFn=*/ getCreateConstIteratorFn(),
- /*.destroyConstIteratorFn=*/ getDestroyConstIteratorFn(),
- /*.equalConstIteratorFn=*/ getCompareConstIteratorFn(),
- /*.copyConstIteratorFn=*/ getCopyConstIteratorFn(),
- /*.advanceConstIteratorFn=*/ getAdvanceConstIteratorFn(),
- /*.diffConstIteratorFn=*/ getDiffConstIteratorFn(),
- /*.valueAtConstIteratorFn=*/ getValueAtConstIteratorFn(),
-};
+QMetaSequenceInterface QMetaSequenceForContainer<C>::metaSequence
+ = QMetaSequenceInterface(QMetaSequenceForContainer<C>());
+
+template<typename C>
+QMetaAssociationInterface QMetaAssociationForContainer<C>::metaAssociation
+ = QMetaAssociationInterface(QMetaAssociationForContainer<C>());
template<typename C>
constexpr QMetaSequenceInterface *qMetaSequenceInterfaceForContainer()
@@ -596,13 +936,58 @@ constexpr QMetaSequenceInterface *qMetaSequenceInterfaceForContainer()
return &QMetaSequenceForContainer<C>::metaSequence;
}
+template<typename C>
+constexpr QMetaAssociationInterface *qMetaAssociationInterfaceForContainer()
+{
+ return &QMetaAssociationForContainer<C>::metaAssociation;
+}
+
} // namespace QtMetaContainerPrivate
-class Q_CORE_EXPORT QMetaSequence
+class Q_CORE_EXPORT QMetaContainer
+{
+public:
+ QMetaContainer() = default;
+ explicit QMetaContainer(const QtMetaContainerPrivate::QMetaContainerInterface *d) : d_ptr(d) {}
+
+ bool hasInputIterator() const;
+ bool hasForwardIterator() const;
+ bool hasBidirectionalIterator() const;
+ bool hasRandomAccessIterator() const;
+
+ bool hasSize() const;
+ qsizetype size(const void *container) const;
+
+ bool canClear() const;
+ void clear(void *container) const;
+
+ bool hasIterator() const;
+ void *begin(void *container) const;
+ void *end(void *container) const;
+ void destroyIterator(const void *iterator) const;
+ bool compareIterator(const void *i, const void *j) const;
+ void copyIterator(void *target, const void *source) const;
+ void advanceIterator(void *iterator, qsizetype step) const;
+ qsizetype diffIterator(const void *i, const void *j) const;
+
+ bool hasConstIterator() const;
+ void *constBegin(const void *container) const;
+ void *constEnd(const void *container) const;
+ void destroyConstIterator(const void *iterator) const;
+ bool compareConstIterator(const void *i, const void *j) const;
+ void copyConstIterator(void *target, const void *source) const;
+ void advanceConstIterator(void *iterator, qsizetype step) const;
+ qsizetype diffConstIterator(const void *i, const void *j) const;
+
+protected:
+ const QtMetaContainerPrivate::QMetaContainerInterface *d_ptr = nullptr;
+};
+
+class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
{
public:
QMetaSequence() = default;
- explicit QMetaSequence(QtMetaContainerPrivate::QMetaSequenceInterface *d) : d_ptr(d) {}
+ explicit QMetaSequence(QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
template<typename T>
static constexpr QMetaSequence fromContainer()
@@ -610,11 +995,6 @@ public:
return QMetaSequence(QtMetaContainerPrivate::qMetaSequenceInterfaceForContainer<T>());
}
- bool hasInputIterator() const;
- bool hasForwardIterator() const;
- bool hasBidirectionalIterator() const;
- bool hasRandomAccessIterator() const;
-
QMetaType valueMetaType() const;
bool isSortable() const;
@@ -627,12 +1007,6 @@ public:
bool canRemoveValueAtEnd() const;
void removeValueAtEnd(void *container) const;
- bool hasSize() const;
- qsizetype size(const void *container) const;
-
- bool canClear() const;
- void clear(void *container) const;
-
bool canGetValueAtIndex() const;
void valueAtIndex(const void *container, qsizetype index, void *result) const;
@@ -645,15 +1019,6 @@ public:
bool canRemoveValue() const;
void removeValue(void *container) const;
- bool hasIterator() const;
- void *begin(void *container) const;
- void *end(void *container) const;
- void destroyIterator(const void *iterator) const;
- bool compareIterator(const void *i, const void *j) const;
- void copyIterator(void *target, const void *source) const;
- void advanceIterator(void *iterator, qsizetype step) const;
- qsizetype diffIterator(const void *i, const void *j) const;
-
bool canGetValueAtIterator() const;
void valueAtIterator(const void *iterator, void *result) const;
@@ -666,15 +1031,6 @@ public:
bool canEraseValueAtIterator() const;
void eraseValueAtIterator(void *container, const void *iterator) const;
- bool hasConstIterator() const;
- void *constBegin(const void *container) const;
- void *constEnd(const void *container) const;
- void destroyConstIterator(const void *iterator) const;
- bool compareConstIterator(const void *i, const void *j) const;
- void copyConstIterator(void *target, const void *source) const;
- void advanceConstIterator(void *iterator, qsizetype step) const;
- qsizetype diffConstIterator(const void *i, const void *j) const;
-
bool canEraseRangeAtIterator() const;
void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
@@ -683,15 +1039,204 @@ public:
friend bool operator==(const QMetaSequence &a, const QMetaSequence &b)
{
- return a.d_ptr == b.d_ptr;
+ return a.d() == b.d();
}
friend bool operator!=(const QMetaSequence &a, const QMetaSequence &b)
{
- return a.d_ptr != b.d_ptr;
+ return a.d() != b.d();
+ }
+
+private:
+ const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
+ {
+ return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
+ }
+};
+
+class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
+{
+public:
+ QMetaAssociation() = default;
+ explicit QMetaAssociation(QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
+
+ template<typename T>
+ static constexpr QMetaAssociation fromContainer()
+ {
+ return QMetaAssociation(QtMetaContainerPrivate::qMetaAssociationInterfaceForContainer<T>());
+ }
+
+ QMetaType keyMetaType() const;
+ QMetaType mappedMetaType() const;
+
+ bool canInsertKey() const
+ {
+ if (auto iface = d())
+ return iface->insertKeyFn;
+ return false;
+ }
+ void insertKey(void *container, const void *key) const
+ {
+ if (canInsertKey())
+ d()->insertKeyFn(container, key);
+ }
+
+ bool canRemoveKey() const
+ {
+ if (auto iface = d())
+ return iface->removeKeyFn;
+ return false;
+ }
+ void removeKey(void *container, const void *key) const
+ {
+ if (canRemoveKey())
+ d()->removeKeyFn(container, key);
+ }
+
+ bool canContainsKey() const
+ {
+ if (auto iface = d())
+ return iface->containsKeyFn;
+ return false;
+ }
+ bool containsKey(const void *container, const void *key) const
+ {
+ if (canContainsKey())
+ return d()->containsKeyFn(container, key);
+ return false;
+ }
+
+
+ bool canGetMappedAtKey() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtKeyFn;
+ return false;
+ }
+ void mappedAtKey(const void *container, const void *key, void *mapped) const
+ {
+ if (canGetMappedAtKey())
+ d()->mappedAtKeyFn(container, key, mapped);
+ }
+
+ bool canSetMappedAtKey() const
+ {
+ if (auto iface = d())
+ return iface->setMappedAtKeyFn;
+ return false;
+ }
+ void setMappedAtKey(void *container, const void *key, const void *mapped) const
+ {
+ if (canSetMappedAtKey())
+ d()->setMappedAtKeyFn(container, key, mapped);
+ }
+
+ bool canGetKeyAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->keyAtIteratorFn;
+ return false;
+ }
+
+ void keyAtIterator(const void *iterator, void *key) const
+ {
+ if (canGetKeyAtIterator())
+ d()->keyAtIteratorFn(iterator, key);
+ }
+
+ bool canGetKeyAtConstIterator() const
+ {
+ if (auto iface = d())
+ return iface->keyAtConstIteratorFn;
+ return false;
+ }
+
+ void keyAtConstIterator(const void *iterator, void *key) const
+ {
+ if (canGetKeyAtConstIterator())
+ d()->keyAtConstIteratorFn(iterator, key);
+ }
+
+ bool canGetMappedAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtIteratorFn;
+ return false;
+ }
+
+ void mappedAtIterator(const void *iterator, void *mapped) const
+ {
+ if (canGetMappedAtIterator())
+ d()->mappedAtIteratorFn(iterator, mapped);
+ }
+
+ bool canGetMappedAtConstIterator() const
+ {
+ if (auto iface = d())
+ return iface->mappedAtConstIteratorFn;
+ return false;
+ }
+
+ void mappedAtConstIterator(const void *iterator, void *mapped) const
+ {
+ if (canGetMappedAtConstIterator())
+ d()->mappedAtConstIteratorFn(iterator, mapped);
+ }
+
+ bool canSetMappedAtIterator() const
+ {
+ if (auto iface = d())
+ return iface->setMappedAtIteratorFn;
+ return false;
+ }
+
+ void setMappedAtIterator(const void *iterator, const void *mapped) const
+ {
+ if (canSetMappedAtIterator())
+ d()->setMappedAtIteratorFn(iterator, mapped);
+ }
+
+ bool canCreateIteratorAtKey() const
+ {
+ if (auto iface = d())
+ return iface->createIteratorAtKeyFn;
+ return false;
+ }
+
+ void *createIteratorAtKey(void *container, const void *key) const
+ {
+ if (canCreateIteratorAtKey())
+ return d()->createIteratorAtKeyFn(container, key);
+ return nullptr;
+ }
+
+ bool canCreateConstIteratorAtKey() const
+ {
+ if (auto iface = d())
+ return iface->createConstIteratorAtKeyFn;
+ return false;
+ }
+
+ void *createConstIteratorAtKey(const void *container, const void *key) const
+ {
+ if (canCreateConstIteratorAtKey())
+ return d()->createConstIteratorAtKeyFn(container, key);
+ return nullptr;
+ }
+
+ friend bool operator==(const QMetaAssociation &a, const QMetaAssociation &b)
+ {
+ return a.d() == b.d();
+ }
+ friend bool operator!=(const QMetaAssociation &a, const QMetaAssociation &b)
+ {
+ return a.d() != b.d();
}
private:
- const QtMetaContainerPrivate::QMetaSequenceInterface *d_ptr = nullptr;
+ const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
+ {
+ return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
+ }
};
QT_END_NAMESPACE
diff --git a/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp b/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
index c4892de2cc..4bfef31b00 100644
--- a/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
+++ b/tests/auto/corelib/kernel/qmetacontainer/tst_qmetacontainer.cpp
@@ -38,6 +38,7 @@
#include <vector>
#include <set>
#include <forward_list>
+#include <unordered_map>
namespace CheckContainerTraits
{
@@ -57,12 +58,12 @@ static_assert(QContainerTraits::has_clear_v<std::vector<int>>);
static_assert(QContainerTraits::has_clear_v<std::set<int>>);
static_assert(QContainerTraits::has_clear_v<std::forward_list<int>>);
-static_assert(QContainerTraits::has_at_v<QVector<int>>);
-static_assert(!QContainerTraits::has_at_v<QSet<int>>);
-static_assert(!QContainerTraits::has_at_v<NotAContainer>);
-static_assert(QContainerTraits::has_at_v<std::vector<int>>);
-static_assert(!QContainerTraits::has_at_v<std::set<int>>);
-static_assert(!QContainerTraits::has_at_v<std::forward_list<int>>);
+static_assert(QContainerTraits::has_at_index_v<QVector<int>>);
+static_assert(!QContainerTraits::has_at_index_v<QSet<int>>);
+static_assert(!QContainerTraits::has_at_index_v<NotAContainer>);
+static_assert(QContainerTraits::has_at_index_v<std::vector<int>>);
+static_assert(!QContainerTraits::has_at_index_v<std::set<int>>);
+static_assert(!QContainerTraits::has_at_index_v<std::forward_list<int>>);
static_assert(QContainerTraits::can_get_at_index_v<QVector<int>>);
static_assert(!QContainerTraits::can_get_at_index_v<QSet<int>>);
@@ -127,30 +128,30 @@ static_assert(QContainerTraits::has_const_iterator_v<std::vector<int>>);
static_assert(QContainerTraits::has_const_iterator_v<std::set<int>>);
static_assert(QContainerTraits::has_const_iterator_v<std::forward_list<int>>);
-static_assert(QContainerTraits::can_get_at_iterator_v<QVector<int>>);
-static_assert(QContainerTraits::can_get_at_iterator_v<QSet<int>>);
-static_assert(!QContainerTraits::can_get_at_iterator_v<NotAContainer>);
-static_assert(QContainerTraits::can_get_at_iterator_v<std::vector<int>>);
-static_assert(QContainerTraits::can_get_at_iterator_v<std::set<int>>);
-static_assert(QContainerTraits::can_get_at_iterator_v<std::forward_list<int>>);
-
-static_assert(QContainerTraits::can_set_at_iterator_v<QVector<int>>);
-static_assert(!QContainerTraits::can_set_at_iterator_v<QSet<int>>);
-static_assert(!QContainerTraits::can_get_at_iterator_v<NotAContainer>);
-static_assert(QContainerTraits::can_set_at_iterator_v<std::vector<int>>);
-static_assert(!QContainerTraits::can_set_at_iterator_v<std::set<int>>);
-static_assert(QContainerTraits::can_set_at_iterator_v<std::forward_list<int>>);
-
-static_assert(QContainerTraits::can_insert_at_iterator_v<QVector<int>>);
-static_assert(!QContainerTraits::can_insert_at_iterator_v<QSet<int>>);
-static_assert(!QContainerTraits::can_insert_at_iterator_v<NotAContainer>);
-static_assert(QContainerTraits::can_insert_at_iterator_v<std::vector<int>>);
-static_assert(!QContainerTraits::can_insert_at_iterator_v<std::forward_list<int>>);
+static_assert(QContainerTraits::iterator_dereferences_to_value_v<QVector<int>>);
+static_assert(QContainerTraits::iterator_dereferences_to_value_v<QSet<int>>);
+static_assert(!QContainerTraits::iterator_dereferences_to_value_v<NotAContainer>);
+static_assert(QContainerTraits::iterator_dereferences_to_value_v<std::vector<int>>);
+static_assert(QContainerTraits::iterator_dereferences_to_value_v<std::set<int>>);
+static_assert(QContainerTraits::iterator_dereferences_to_value_v<std::forward_list<int>>);
+
+static_assert(QContainerTraits::can_set_value_at_iterator_v<QVector<int>>);
+static_assert(!QContainerTraits::can_set_value_at_iterator_v<QSet<int>>);
+static_assert(!QContainerTraits::can_set_value_at_iterator_v<NotAContainer>);
+static_assert(QContainerTraits::can_set_value_at_iterator_v<std::vector<int>>);
+static_assert(!QContainerTraits::can_set_value_at_iterator_v<std::set<int>>);
+static_assert(QContainerTraits::can_set_value_at_iterator_v<std::forward_list<int>>);
+
+static_assert(QContainerTraits::can_insert_value_at_iterator_v<QVector<int>>);
+static_assert(!QContainerTraits::can_insert_value_at_iterator_v<QSet<int>>);
+static_assert(!QContainerTraits::can_insert_value_at_iterator_v<NotAContainer>);
+static_assert(QContainerTraits::can_insert_value_at_iterator_v<std::vector<int>>);
+static_assert(!QContainerTraits::can_insert_value_at_iterator_v<std::forward_list<int>>);
// The iterator is only a hint, but syntactically indistinguishable from others.
// It's explicitly there to be signature compatible with std::vector::insert, though.
// Also, inserting into a set is not guaranteed to actually do anything.
-static_assert(QContainerTraits::can_insert_at_iterator_v<std::set<int>>);
+static_assert(QContainerTraits::can_insert_value_at_iterator_v<std::set<int>>);
static_assert(QContainerTraits::can_erase_at_iterator_v<QVector<int>>);
static_assert(QContainerTraits::can_erase_at_iterator_v<QSet<int>>);
@@ -172,10 +173,19 @@ private:
std::set<int> stdset;
std::forward_list<QMetaSequence> forwardList;
+ QHash<int, QMetaType> qhash;
+ QMap<QByteArray, bool> qmap;
+ std::map<QString, int> stdmap;
+ std::unordered_map<int, QMetaAssociation> stdunorderedmap;
+
private slots:
void init();
void testSequence_data();
void testSequence();
+
+ void testAssociation_data();
+ void testAssociation();
+
void cleanup();
};
@@ -192,6 +202,28 @@ void tst_QMetaContainer::init()
QMetaSequence::fromContainer<std::set<int>>(),
QMetaSequence::fromContainer<std::forward_list<QMetaSequence>>()
};
+ qhash = {
+ { 233, QMetaType() },
+ { 11, QMetaType::fromType<QByteArray>() },
+ { 6626, QMetaType::fromType<bool>() }
+ };
+ qmap = {
+ { "eins", true },
+ { "zwei", false },
+ { "elfundvierzig", true }
+ };
+
+ stdmap = {
+ { QStringLiteral("dkdkdkd"), 58583 },
+ { QStringLiteral("ooo30393"), 12 },
+ { QStringLiteral("2dddd30393"), 999999 },
+ };
+ stdunorderedmap = {
+ { 11, QMetaAssociation::fromContainer<QHash<int, QMetaType>>() },
+ { 12, QMetaAssociation::fromContainer<QMap<QByteArray, bool>>() },
+ { 393, QMetaAssociation::fromContainer<std::map<QString, int>>() },
+ { 293, QMetaAssociation::fromContainer<std::unordered_map<int, QMetaAssociation>>() }
+ };
}
void tst_QMetaContainer::cleanup()
@@ -201,6 +233,10 @@ void tst_QMetaContainer::cleanup()
qset.clear();
stdset.clear();
forwardList.clear();
+ qhash.clear();
+ qmap.clear();
+ stdmap.clear();
+ stdunorderedmap.clear();
}
void tst_QMetaContainer::testSequence_data()
@@ -486,5 +522,230 @@ void tst_QMetaContainer::testSequence()
metaSequence.destroyConstIterator(constEnd);
}
+void tst_QMetaContainer::testAssociation_data()
+{
+ QTest::addColumn<void *>("container");
+ QTest::addColumn<QMetaAssociation>("metaAssociation");
+ QTest::addColumn<QMetaType>("keyType");
+ QTest::addColumn<QMetaType>("mappedType");
+ QTest::addColumn<bool>("hasSize");
+ QTest::addColumn<bool>("canRemove");
+ QTest::addColumn<bool>("canSetMapped");
+ QTest::addColumn<bool>("hasBidirectionalIterator");
+ QTest::addColumn<bool>("hasRandomAccessIterator");
+
+ QTest::addRow("QHash")
+ << static_cast<void *>(&qhash)
+ << QMetaAssociation::fromContainer<QHash<int, QMetaType>>()
+ << QMetaType::fromType<int>()
+ << QMetaType::fromType<QMetaType>()
+ << true << true << true << false << false;
+ QTest::addRow("QMap")
+ << static_cast<void *>(&qmap)
+ << QMetaAssociation::fromContainer<QMap<QByteArray, bool>>()
+ << QMetaType::fromType<QByteArray>()
+ << QMetaType::fromType<bool>()
+ << true << true << true << true << false;
+ QTest::addRow("std::map")
+ << static_cast<void *>(&stdmap)
+ << QMetaAssociation::fromContainer<std::map<QString, int>>()
+ << QMetaType::fromType<QString>()
+ << QMetaType::fromType<int>()
+ << true << true << true << true << false;
+ QTest::addRow("std::unorderedmap")
+ << static_cast<void *>(&stdunorderedmap)
+ << QMetaAssociation::fromContainer<std::unordered_map<int, QMetaAssociation>>()
+ << QMetaType::fromType<int>()
+ << QMetaType::fromType<QMetaAssociation>()
+ << true << true << true << false << false;
+ QTest::addRow("QSet")
+ << static_cast<void *>(&qset)
+ << QMetaAssociation::fromContainer<QSet<QByteArray>>()
+ << QMetaType::fromType<QByteArray>()
+ << QMetaType()
+ << true << true << false << false << false;
+ QTest::addRow("std::set")
+ << static_cast<void *>(&stdset)
+ << QMetaAssociation::fromContainer<std::set<int>>()
+ << QMetaType::fromType<int>()
+ << QMetaType()
+ << true << true << false << true << false;
+}
+
+void tst_QMetaContainer::testAssociation()
+{
+ QFETCH(void *, container);
+ QFETCH(QMetaAssociation, metaAssociation);
+ QFETCH(QMetaType, keyType);
+ QFETCH(QMetaType, mappedType);
+ QFETCH(bool, hasSize);
+ QFETCH(bool, canRemove);
+ QFETCH(bool, canSetMapped);
+ QFETCH(bool, hasBidirectionalIterator);
+ QFETCH(bool, hasRandomAccessIterator);
+
+ QCOMPARE(metaAssociation.hasSize(), hasSize);
+ QCOMPARE(metaAssociation.canRemoveKey(), canRemove);
+ QCOMPARE(metaAssociation.canSetMappedAtKey(), canSetMapped);
+ QCOMPARE(metaAssociation.canSetMappedAtIterator(), canSetMapped);
+
+ // Apparently implementations can choose to provide "better" iterators than required by the std.
+ if (hasBidirectionalIterator)
+ QCOMPARE(metaAssociation.hasBidirectionalIterator(), hasBidirectionalIterator);
+ if (hasRandomAccessIterator)
+ QCOMPARE(metaAssociation.hasRandomAccessIterator(), hasRandomAccessIterator);
+
+ QVariant key1(keyType);
+ QVariant key2(keyType);
+ QVariant key3(keyType);
+
+ QVariant mapped1(mappedType);
+ QVariant mapped2(mappedType);
+ QVariant mapped3(mappedType);
+
+ if (hasSize) {
+ const qsizetype size = metaAssociation.size(container);
+
+ QVERIFY(metaAssociation.canInsertKey());
+
+ // var1 is invalid, and our containers do not contain an invalid key so far.
+ metaAssociation.insertKey(container, key1.constData());
+ QCOMPARE(metaAssociation.size(container), size + 1);
+ metaAssociation.removeKey(container, key1.constData());
+ QCOMPARE(metaAssociation.size(container), size);
+ } else {
+ metaAssociation.insertKey(container, key1.constData());
+ metaAssociation.removeKey(container, key1.constData());
+ }
+
+ QVERIFY(metaAssociation.hasIterator());
+ QVERIFY(metaAssociation.hasConstIterator());
+ QVERIFY(metaAssociation.canGetKeyAtIterator());
+ QVERIFY(metaAssociation.canGetKeyAtConstIterator());
+
+ void *it = metaAssociation.begin(container);
+ void *end = metaAssociation.end(container);
+ QVERIFY(it);
+ QVERIFY(end);
+
+ void *constIt = metaAssociation.constBegin(container);
+ void *constEnd = metaAssociation.constEnd(container);
+ QVERIFY(constIt);
+ QVERIFY(constEnd);
+
+ const qsizetype size = metaAssociation.diffIterator(end, it);
+ QCOMPARE(size, metaAssociation.diffConstIterator(constEnd, constIt));
+ if (hasSize)
+ QCOMPARE(size, metaAssociation.size(container));
+
+ qsizetype count = 0;
+ for (; !metaAssociation.compareIterator(it, end);
+ metaAssociation.advanceIterator(it, 1), metaAssociation.advanceConstIterator(constIt, 1)) {
+ metaAssociation.keyAtIterator(it, key1.data());
+ metaAssociation.keyAtConstIterator(constIt, key3.data());
+ QCOMPARE(key3, key1);
+ ++count;
+ }
+
+ QCOMPARE(count, size);
+ QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd));
+
+ metaAssociation.destroyIterator(it);
+ metaAssociation.destroyIterator(end);
+ metaAssociation.destroyConstIterator(constIt);
+ metaAssociation.destroyConstIterator(constEnd);
+
+ if (metaAssociation.canSetMappedAtIterator()) {
+ void *it = metaAssociation.begin(container);
+ void *end = metaAssociation.end(container);
+ QVERIFY(it);
+ QVERIFY(end);
+
+ for (; !metaAssociation.compareIterator(it, end); metaAssociation.advanceIterator(it, 1)) {
+ metaAssociation.mappedAtIterator(it, mapped1.data());
+ metaAssociation.setMappedAtIterator(it, mapped2.constData());
+ metaAssociation.mappedAtIterator(it, mapped3.data());
+ QCOMPARE(mapped2, mapped3);
+ mapped2 = mapped1;
+ }
+
+ metaAssociation.destroyIterator(it);
+ metaAssociation.destroyIterator(end);
+
+ it = metaAssociation.constBegin(container);
+ end = metaAssociation.constEnd(container);
+ QVERIFY(it);
+ QVERIFY(end);
+
+ for (; !metaAssociation.compareConstIterator(it, end); metaAssociation.advanceConstIterator(it, 1)) {
+ metaAssociation.mappedAtConstIterator(it, mapped1.data());
+ metaAssociation.keyAtConstIterator(it, key1.data());
+ metaAssociation.setMappedAtKey(container, key1.constData(), mapped2.constData());
+ metaAssociation.mappedAtConstIterator(it, mapped3.data());
+ QCOMPARE(mapped2, mapped3);
+ mapped2 = mapped1;
+ }
+
+ metaAssociation.destroyConstIterator(it);
+ metaAssociation.destroyConstIterator(end);
+ }
+
+ if (metaAssociation.hasBidirectionalIterator()) {
+ void *it = metaAssociation.end(container);
+ void *end = metaAssociation.begin(container);
+ QVERIFY(it);
+ QVERIFY(end);
+
+ void *constIt = metaAssociation.constEnd(container);
+ void *constEnd = metaAssociation.constBegin(container);
+ QVERIFY(constIt);
+ QVERIFY(constEnd);
+
+ qsizetype size = 0;
+ if (metaAssociation.hasRandomAccessIterator()) {
+ size = metaAssociation.diffIterator(end, it);
+ QCOMPARE(size, metaAssociation.diffConstIterator(constEnd, constIt));
+ } else {
+ size = -metaAssociation.diffIterator(it, end);
+ }
+
+ if (hasSize)
+ QCOMPARE(size, -metaAssociation.size(container));
+
+ qsizetype count = 0;
+ do {
+ metaAssociation.advanceIterator(it, -1);
+ metaAssociation.advanceConstIterator(constIt, -1);
+ --count;
+
+ metaAssociation.keyAtIterator(it, key1.data());
+ metaAssociation.keyAtConstIterator(constIt, key3.data());
+ QCOMPARE(key3, key1);
+ } while (!metaAssociation.compareIterator(it, end));
+
+ QCOMPARE(count, size);
+ QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd));
+
+ metaAssociation.destroyIterator(it);
+ metaAssociation.destroyIterator(end);
+ metaAssociation.destroyConstIterator(constIt);
+ metaAssociation.destroyConstIterator(constEnd);
+ }
+
+ QVERIFY(metaAssociation.canClear());
+ constIt = metaAssociation.constBegin(container);
+ constEnd = metaAssociation.constEnd(container);
+ QVERIFY(!metaAssociation.compareConstIterator(constIt, constEnd));
+ metaAssociation.destroyConstIterator(constIt);
+ metaAssociation.destroyConstIterator(constEnd);
+
+ metaAssociation.clear(container);
+ constIt = metaAssociation.constBegin(container);
+ constEnd = metaAssociation.constEnd(container);
+ QVERIFY(metaAssociation.compareConstIterator(constIt, constEnd));
+ metaAssociation.destroyConstIterator(constIt);
+ metaAssociation.destroyConstIterator(constEnd);
+}
+
QTEST_MAIN(tst_QMetaContainer)
#include "tst_qmetacontainer.moc"
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index a6c0ecb012..7be1ea19d7 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -4558,7 +4558,7 @@ void tst_QVariant::shouldDeleteVariantDataWorksForSequential()
MyType mytype {2, "zwei"};
*static_cast<MyType *>(dataPtr) = mytype;
};
- metaSequence.valueMetaType = QMetaType::fromType<MyType>();
+ metaSequence.valueMetaType = QtPrivate::qMetaTypeInterfaceForType<MyType>();
QSequentialIterable iterable(QMetaSequence(&metaSequence), nullptr);
QVariant value1 = iterable.at(0);