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 @@ -51,6 +51,12 @@ namespace QContainerTraits template using value_type = typename C::value_type; +template +using key_type = typename C::key_type; + +template +using mapped_type = typename C::mapped_type; + template using iterator = typename C::iterator; @@ -61,6 +67,21 @@ using const_iterator = typename C::const_iterator; QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wunused-const-variable") +template +constexpr bool has_value_type_v = false; +template +constexpr bool has_value_type_v>> = true; + +template +constexpr bool has_key_type_v = false; +template +constexpr bool has_key_type_v>> = true; + +template +constexpr bool has_mapped_type_v = false; +template +constexpr bool has_mapped_type_v>> = true; + template constexpr bool has_size_v = false; template @@ -72,9 +93,14 @@ template constexpr bool has_clear_v> = true; template -constexpr bool has_at_v = false; +constexpr bool has_at_index_v = false; template -constexpr bool has_at_v> = true; +constexpr bool has_at_index_v> = true; + +template +constexpr bool has_at_key_v = false; +template +constexpr bool has_at_key_v()))>> = true; template constexpr bool can_get_at_index_v = false; @@ -122,19 +148,19 @@ template constexpr bool has_const_iterator_v>> = true; template -constexpr bool can_get_at_iterator_v = false; +constexpr bool can_set_value_at_iterator_v = false; template -constexpr bool can_get_at_iterator_v(decltype(*C().begin()))>> = true; +constexpr bool can_set_value_at_iterator_v())>> = true; template -constexpr bool can_set_at_iterator_v = false; +constexpr bool can_set_mapped_at_iterator_v = false; template -constexpr bool can_set_at_iterator_v())>> = true; +constexpr bool can_set_mapped_at_iterator_v())>> = true; template -constexpr bool can_insert_at_iterator_v = false; +constexpr bool can_insert_value_at_iterator_v = false; template -constexpr bool can_insert_at_iterator_v()))>> = true; +constexpr bool can_insert_value_at_iterator_v()))>> = true; template constexpr bool can_erase_at_iterator_v = false; @@ -146,6 +172,86 @@ constexpr bool can_erase_range_at_iterator_v = false; template constexpr bool can_erase_range_at_iterator_v> = true; +template +constexpr bool can_get_at_key_v = false; +template +constexpr bool can_get_at_key_v(decltype(C()[key_type()]))>> = true; + +template +constexpr bool can_set_at_key_v = false; +template +constexpr bool can_set_at_key_v()] = mapped_type())>> = true; + +template +constexpr bool can_erase_at_key_v = false; +template +constexpr bool can_erase_at_key_v()))>> = true; + +template +constexpr bool can_remove_at_key_v = false; +template +constexpr bool can_remove_at_key_v()))>> = true; + +template +constexpr bool can_insert_key_v = false; +template +constexpr bool can_insert_key_v()))>> = true; + +template +constexpr bool can_insert_pair_v = false; +template +constexpr bool can_insert_pair_v(), mapped_type()}))>> = true; + +template +constexpr bool can_insert_key_mapped_v = false; +template +constexpr bool can_insert_key_mapped_v(), mapped_type()))>> = true; + +template +constexpr bool has_contains_v = false; +template +constexpr bool has_contains_v())))>> = true; + +template +constexpr bool has_find_v = false; +template +constexpr bool has_find_v()))>> = true; + +template +constexpr bool iterator_dereferences_to_value_v = false; +template +constexpr bool iterator_dereferences_to_value_v(*C().begin()))>> = true; + +template +constexpr bool iterator_has_key_v = false; +template +constexpr bool iterator_has_key_v(C().begin().key()))>> = true; + +template +constexpr bool value_type_has_first_v = false; +template +constexpr bool value_type_has_first_v(value_type().first))>> = true; + +template +constexpr bool iterator_dereferences_to_key_v = false; +template +constexpr bool iterator_dereferences_to_key_v(*C().begin()))>> = true; + +template +constexpr bool iterator_has_value_v = false; +template +constexpr bool iterator_has_value_v(C().begin().value()))>> = true; + +template +constexpr bool value_type_has_second_v = false; +template +constexpr bool value_type_has_second_v(value_type().second))>> = true; + +template +constexpr bool iterator_dereferences_to_mapped_v = false; +template +constexpr bool iterator_dereferences_to_mapped_v(*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 #include #include -#include QT_BEGIN_NAMESPACE +class QMetaType; +namespace QtPrivate { +class QMetaTypeInterface; +template +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,16 +98,6 @@ public: AdvanceIteratorFn advanceIteratorFn; using DiffIteratorFn = qsizetype(*)(const void *, const void *); DiffIteratorFn diffIteratorFn; - 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; - 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; @@ -123,12 +106,145 @@ public: CopyIteratorFn copyConstIteratorFn; AdvanceIteratorFn advanceConstIteratorFn; DiffIteratorFn diffConstIteratorFn; + + QMetaContainerInterface() = default; + + template + 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; + + QMetaSequenceInterface() = default; + + template + 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 + 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 -class QMetaSequenceForContainer +class QMetaContainerForContainer { + friend QMetaContainerInterface; + template static constexpr IteratorCapabilities capabilitiesForIterator() { @@ -155,6 +271,213 @@ class QMetaSequenceForContainer return {}; } + static constexpr QMetaContainerInterface::SizeFn getSizeFn() + { + if constexpr (QContainerTraits::has_size_v) { + return [](const void *c) -> qsizetype { return static_cast(c)->size(); }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::ClearFn getClearFn() + { + if constexpr (QContainerTraits::has_clear_v) { + return [](void *c) { return static_cast(c)->clear(); }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *c, QMetaContainerInterface::Position p) -> void* { + using Iterator = QContainerTraits::iterator; + switch (p) { + case QMetaContainerInterface::Unspecified: + return new Iterator; + case QMetaContainerInterface::AtBegin: + return new Iterator(static_cast(c)->begin()); + break; + case QMetaContainerInterface::AtEnd: + return new Iterator(static_cast(c)->end()); + break; + } + return nullptr; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i) { + using Iterator = QContainerTraits::iterator; + delete static_cast(i); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i, const void *j) { + using Iterator = QContainerTraits::iterator; + return *static_cast(i) == *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *i, const void *j) { + using Iterator = QContainerTraits::iterator; + *static_cast(i) = *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](void *i, qsizetype step) { + std::advance(*static_cast *>(i), step); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { + return [](const void *i, const void *j) -> qsizetype { + return std::distance(*static_cast *>(j), + *static_cast *>(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *c, QMetaContainerInterface::Position p) -> void* { + using Iterator = QContainerTraits::const_iterator; + switch (p) { + case QMetaContainerInterface::Unspecified: + return new Iterator; + case QMetaContainerInterface::AtBegin: + return new Iterator(static_cast(c)->begin()); + case QMetaContainerInterface::AtEnd: + return new Iterator(static_cast(c)->end()); + } + return nullptr; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i) { + using Iterator = QContainerTraits::const_iterator; + delete static_cast(i); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i, const void *j) { + using Iterator = QContainerTraits::const_iterator; + return *static_cast(i) == *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](void *i, const void *j) { + using Iterator = QContainerTraits::const_iterator; + *static_cast(i) = *static_cast(j); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](void *i, qsizetype step) { + std::advance(*static_cast *>(i), step); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn() + { + if constexpr (QContainerTraits::has_const_iterator_v) { + return [](const void *i, const void *j) -> qsizetype { + return std::distance(*static_cast *>(j), + *static_cast *>(i)); + }; + } else { + return nullptr; + } + } + +protected: + + template + static constexpr EraseFn getEraseAtIteratorFn() + { + if constexpr (QContainerTraits::has_iterator_v + && QContainerTraits::can_erase_at_iterator_v && !std::is_const_v) { + return [](void *c, const void *i) { + static_cast(c)->erase(*static_cast *>(i)); + }; + } else { + return nullptr; + } + } +}; + +template +class QMetaSequenceForContainer : public QMetaContainerForContainer +{ + friend QMetaSequenceInterface; + + static constexpr QtPrivate::QMetaTypeInterface *getValueMetaType() + { + if constexpr (QContainerTraits::has_value_type_v) + return QtPrivate::qMetaTypeInterfaceForType(); + else + return nullptr; + } + static constexpr AddRemoveCapabilities getAddRemoveCapabilities() { AddRemoveCapabilities caps; @@ -169,32 +492,9 @@ class QMetaSequenceForContainer return caps; } - static constexpr QMetaType getValueMetaType() - { - return QMetaType::fromType(); - } - - static constexpr QMetaSequenceInterface::SizeFn getSizeFn() - { - if constexpr (QContainerTraits::has_size_v) { - return [](const void *c) -> qsizetype { return static_cast(c)->size(); }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::ClearFn getClearFn() - { - if constexpr (QContainerTraits::has_clear_v) { - return [](void *c) { return static_cast(c)->clear(); }; - } else { - return nullptr; - } - } - static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn() { - if constexpr (QContainerTraits::has_at_v) { + if constexpr (QContainerTraits::has_at_index_v) { return [](const void *c, qsizetype i, void *r) { *static_cast *>(r) = static_cast(c)->at(i); @@ -316,90 +616,10 @@ class QMetaSequenceForContainer } } - static constexpr QMetaSequenceInterface::CreateIteratorFn getCreateIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](void *c, QMetaSequenceInterface::Position p) -> void* { - using Iterator = QContainerTraits::iterator; - switch (p) { - case QMetaSequenceInterface::AtBegin: - case QMetaSequenceInterface::Unspecified: - return new Iterator(static_cast(c)->begin()); - break; - case QMetaSequenceInterface::AtEnd: - return new Iterator(static_cast(c)->end()); - break; - } - return nullptr; - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](const void *i) { - using Iterator = QContainerTraits::iterator; - delete static_cast(i); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](const void *i, const void *j) { - using Iterator = QContainerTraits::iterator; - return *static_cast(i) == *static_cast(j); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](void *i, const void *j) { - using Iterator = QContainerTraits::iterator; - *static_cast(i) = *static_cast(j); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](void *i, qsizetype step) { - std::advance(*static_cast *>(i), step); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffIteratorFn() - { - if constexpr (QContainerTraits::has_iterator_v && !std::is_const_v) { - return [](const void *i, const void *j) -> qsizetype { - return std::distance(*static_cast *>(j), - *static_cast *>(i)); - }; - } else { - return nullptr; - } - } - static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn() { if constexpr (QContainerTraits::has_iterator_v - && QContainerTraits::can_get_at_iterator_v && !std::is_const_v) { + && QContainerTraits::iterator_dereferences_to_value_v && !std::is_const_v) { return [](const void *i, void *r) { *static_cast *>(r) = *(*static_cast *>(i)); @@ -412,7 +632,7 @@ class QMetaSequenceForContainer static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn() { if constexpr (QContainerTraits::has_iterator_v - && QContainerTraits::can_set_at_iterator_v && !std::is_const_v) { + && QContainerTraits::can_set_value_at_iterator_v && !std::is_const_v) { return [](const void *i, const void *e) { *(*static_cast *>(i)) = *static_cast *>(e); @@ -425,7 +645,7 @@ class QMetaSequenceForContainer static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn() { if constexpr (QContainerTraits::has_iterator_v - && QContainerTraits::can_insert_at_iterator_v && !std::is_const_v) { + && QContainerTraits::can_insert_value_at_iterator_v && !std::is_const_v) { return [](void *c, const void *i, const void *e) { static_cast(c)->insert( *static_cast *>(i), @@ -436,18 +656,25 @@ class QMetaSequenceForContainer } } - static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn() + static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn() { - if constexpr (QContainerTraits::has_iterator_v - && QContainerTraits::can_erase_at_iterator_v && !std::is_const_v) { - return [](void *c, const void *i) { - static_cast(c)->erase(*static_cast *>(i)); + if constexpr (QContainerTraits::has_const_iterator_v + && QContainerTraits::iterator_dereferences_to_value_v) { + return [](const void *i, void *r) { + *static_cast *>(r) = + *(*static_cast *>(i)); }; } else { return nullptr; } } + static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn() + { + return QMetaContainerForContainer::template getEraseAtIteratorFn< + QMetaSequenceInterface::EraseValueAtIteratorFn>(); + } + static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn() { if constexpr (QContainerTraits::has_iterator_v @@ -461,148 +688,306 @@ class QMetaSequenceForContainer } } - static constexpr QMetaSequenceInterface::CreateConstIteratorFn getCreateConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](const void *c, QMetaSequenceInterface::Position p) -> void* { - using Iterator = QContainerTraits::const_iterator; - switch (p) { - case QMetaSequenceInterface::AtBegin: - case QMetaSequenceInterface::Unspecified: - return new Iterator(static_cast(c)->begin()); - break; - case QMetaSequenceInterface::AtEnd: - return new Iterator(static_cast(c)->end()); - break; - } - return nullptr; - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::DestroyIteratorFn getDestroyConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](const void *i) { - using Iterator = QContainerTraits::const_iterator; - delete static_cast(i); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::CompareIteratorFn getCompareConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](const void *i, const void *j) { - using Iterator = QContainerTraits::const_iterator; - return *static_cast(i) == *static_cast(j); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::CopyIteratorFn getCopyConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](void *i, const void *j) { - using Iterator = QContainerTraits::const_iterator; - *static_cast(i) = *static_cast(j); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::AdvanceIteratorFn getAdvanceConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](void *i, qsizetype step) { - std::advance(*static_cast *>(i), step); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::DiffIteratorFn getDiffConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v) { - return [](const void *i, const void *j) -> qsizetype { - return std::distance(*static_cast *>(j), - *static_cast *>(i)); - }; - } else { - return nullptr; - } - } - - static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn() - { - if constexpr (QContainerTraits::has_const_iterator_v - && QContainerTraits::can_get_at_iterator_v) { - return [](const void *i, void *r) { - *static_cast *>(r) = - *(*static_cast *>(i)); - }; - } else { - return nullptr; - } - } - public: static QMetaSequenceInterface metaSequence; }; template -QMetaSequenceInterface QMetaSequenceForContainer::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(), +class QMetaAssociationForContainer : public QMetaContainerForContainer +{ + friend QMetaAssociationInterface; + + static constexpr QtPrivate::QMetaTypeInterface *getKeyMetaType() + { + if constexpr (QContainerTraits::has_key_type_v) + return QtPrivate::qMetaTypeInterfaceForType(); + else + return nullptr; + } + + static constexpr QtPrivate::QMetaTypeInterface *getMappedMetaType() + { + if constexpr (QContainerTraits::has_mapped_type_v) + return QtPrivate::qMetaTypeInterfaceForType(); + else + return nullptr; + } + + static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn() + { + if constexpr (QContainerTraits::can_insert_key_v) { + return [](void *c, const void *k) { + static_cast(c)->insert( + *static_cast *>(k)); + }; + } else if constexpr (QContainerTraits::can_insert_pair_v) { + return [](void *c, const void *k) { + static_cast(c)->insert( + {*static_cast *>(k), {}}); + }; + } else if constexpr (QContainerTraits::can_insert_key_mapped_v) { + return [](void *c, const void *k) { + static_cast(c)->insert( + *static_cast *>(k), {}); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn() + { + if constexpr (QContainerTraits::can_erase_at_key_v) { + return [](void *c, const void *k) { + static_cast(c)->erase(*static_cast *>(k)); + }; + } else if constexpr (QContainerTraits::can_remove_at_key_v) { + return [](void *c, const void *k) { + static_cast(c)->remove(*static_cast *>(k)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn() + { + if constexpr (QContainerTraits::has_contains_v) { + return [](const void *c, const void *k) { + return static_cast(c)->contains( + *static_cast *>(k)); + }; + } else if (QContainerTraits::has_find_v) { + return [](const void *c, const void *k) { + const C *container = static_cast(c); + return container->find( + *static_cast *>(k)) + != container->end(); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn() + { + if constexpr (QContainerTraits::has_at_key_v) { + return [](const void *c, const void *k, void *r) { + *static_cast *>(r) + = static_cast(c)->at( + *static_cast *>(k)); + }; + } else if constexpr (QContainerTraits::can_get_at_key_v) { + return [](const void *c, const void *k, void *r) { + *static_cast *>(r) + = (*static_cast(c))[ + *static_cast *>(k)]; + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn() + { + if constexpr (QContainerTraits::can_set_at_key_v) { + return [](void *c, const void *k, const void *m) { + (*static_cast(c))[*static_cast *>(k)] = + *static_cast *>(m); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn() + { + if constexpr (QContainerTraits::has_find_v) { + return [](void *c, const void *k) -> void* { + using Iterator = QContainerTraits::iterator; + return new Iterator(static_cast(c)->find( + *static_cast *>(k))); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn() + { + if constexpr (QContainerTraits::has_find_v) { + return [](const void *c, const void *k) -> void* { + using Iterator = QContainerTraits::const_iterator; + return new Iterator(static_cast(c)->find( + *static_cast *>(k))); + }; + } else { + return nullptr; + } + } + + template + static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn() + { + if constexpr (QContainerTraits::iterator_has_key_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = static_cast(i)->key(); + }; + } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v + && QContainerTraits::value_type_has_first_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = (*static_cast(i))->first; + }; + } else if constexpr (QContainerTraits::iterator_dereferences_to_key_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = *(*static_cast(i)); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn() + { + return keyAtIteratorFn>(); + } + + static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn() + { + return keyAtIteratorFn>(); + } + + template + static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn() + { + if constexpr (QContainerTraits::iterator_has_value_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = static_cast(i)->value(); + }; + } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v + && QContainerTraits::value_type_has_second_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = (*static_cast(i))->second; + }; + } else if constexpr (QContainerTraits::iterator_dereferences_to_mapped_v) { + return [](const void *i, void *k) { + *static_cast *>(k) + = *static_cast(i); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn() + { + return mappedAtIteratorFn>(); + } + + static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn() + { + return mappedAtIteratorFn>(); + } + + static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn() + { + if constexpr (QContainerTraits::can_set_mapped_at_iterator_v && !std::is_const_v) { + return [](const void *i, const void *m) { + *(*static_cast *>(i)) + = *static_cast *>(m); + }; + } else if constexpr (QContainerTraits::iterator_dereferences_to_value_v + && QContainerTraits::value_type_has_second_v) { + return [](const void *i, const void *m) { + (*static_cast *>(i))->second + = *static_cast *>(m); + }; + } else { + return nullptr; + } + } + + static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn() + { + return QMetaContainerForContainer::template getEraseAtIteratorFn< + QMetaAssociationInterface::EraseKeyAtIteratorFn>(); + } + +public: + static QMetaAssociationInterface metaAssociation; }; +template +QMetaSequenceInterface QMetaSequenceForContainer::metaSequence + = QMetaSequenceInterface(QMetaSequenceForContainer()); + +template +QMetaAssociationInterface QMetaAssociationForContainer::metaAssociation + = QMetaAssociationInterface(QMetaAssociationForContainer()); + template constexpr QMetaSequenceInterface *qMetaSequenceInterfaceForContainer() { return &QMetaSequenceForContainer::metaSequence; } +template +constexpr QMetaAssociationInterface *qMetaAssociationInterfaceForContainer() +{ + return &QMetaAssociationForContainer::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 static constexpr QMetaSequence fromContainer() @@ -610,11 +995,6 @@ public: return QMetaSequence(QtMetaContainerPrivate::qMetaSequenceInterfaceForContainer()); } - 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_ptr = nullptr; + const QtMetaContainerPrivate::QMetaSequenceInterface *d() const + { + return static_cast(d_ptr); + } +}; + +class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer +{ +public: + QMetaAssociation() = default; + explicit QMetaAssociation(QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {} + + template + static constexpr QMetaAssociation fromContainer() + { + return QMetaAssociation(QtMetaContainerPrivate::qMetaAssociationInterfaceForContainer()); + } + + 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::QMetaAssociationInterface *d() const + { + return static_cast(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 #include #include +#include namespace CheckContainerTraits { @@ -57,12 +58,12 @@ static_assert(QContainerTraits::has_clear_v>); static_assert(QContainerTraits::has_clear_v>); static_assert(QContainerTraits::has_clear_v>); -static_assert(QContainerTraits::has_at_v>); -static_assert(!QContainerTraits::has_at_v>); -static_assert(!QContainerTraits::has_at_v); -static_assert(QContainerTraits::has_at_v>); -static_assert(!QContainerTraits::has_at_v>); -static_assert(!QContainerTraits::has_at_v>); +static_assert(QContainerTraits::has_at_index_v>); +static_assert(!QContainerTraits::has_at_index_v>); +static_assert(!QContainerTraits::has_at_index_v); +static_assert(QContainerTraits::has_at_index_v>); +static_assert(!QContainerTraits::has_at_index_v>); +static_assert(!QContainerTraits::has_at_index_v>); static_assert(QContainerTraits::can_get_at_index_v>); static_assert(!QContainerTraits::can_get_at_index_v>); @@ -127,30 +128,30 @@ static_assert(QContainerTraits::has_const_iterator_v>); static_assert(QContainerTraits::has_const_iterator_v>); static_assert(QContainerTraits::has_const_iterator_v>); -static_assert(QContainerTraits::can_get_at_iterator_v>); -static_assert(QContainerTraits::can_get_at_iterator_v>); -static_assert(!QContainerTraits::can_get_at_iterator_v); -static_assert(QContainerTraits::can_get_at_iterator_v>); -static_assert(QContainerTraits::can_get_at_iterator_v>); -static_assert(QContainerTraits::can_get_at_iterator_v>); +static_assert(QContainerTraits::iterator_dereferences_to_value_v>); +static_assert(QContainerTraits::iterator_dereferences_to_value_v>); +static_assert(!QContainerTraits::iterator_dereferences_to_value_v); +static_assert(QContainerTraits::iterator_dereferences_to_value_v>); +static_assert(QContainerTraits::iterator_dereferences_to_value_v>); +static_assert(QContainerTraits::iterator_dereferences_to_value_v>); -static_assert(QContainerTraits::can_set_at_iterator_v>); -static_assert(!QContainerTraits::can_set_at_iterator_v>); -static_assert(!QContainerTraits::can_get_at_iterator_v); -static_assert(QContainerTraits::can_set_at_iterator_v>); -static_assert(!QContainerTraits::can_set_at_iterator_v>); -static_assert(QContainerTraits::can_set_at_iterator_v>); +static_assert(QContainerTraits::can_set_value_at_iterator_v>); +static_assert(!QContainerTraits::can_set_value_at_iterator_v>); +static_assert(!QContainerTraits::can_set_value_at_iterator_v); +static_assert(QContainerTraits::can_set_value_at_iterator_v>); +static_assert(!QContainerTraits::can_set_value_at_iterator_v>); +static_assert(QContainerTraits::can_set_value_at_iterator_v>); -static_assert(QContainerTraits::can_insert_at_iterator_v>); -static_assert(!QContainerTraits::can_insert_at_iterator_v>); -static_assert(!QContainerTraits::can_insert_at_iterator_v); -static_assert(QContainerTraits::can_insert_at_iterator_v>); -static_assert(!QContainerTraits::can_insert_at_iterator_v>); +static_assert(QContainerTraits::can_insert_value_at_iterator_v>); +static_assert(!QContainerTraits::can_insert_value_at_iterator_v>); +static_assert(!QContainerTraits::can_insert_value_at_iterator_v); +static_assert(QContainerTraits::can_insert_value_at_iterator_v>); +static_assert(!QContainerTraits::can_insert_value_at_iterator_v>); // 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>); +static_assert(QContainerTraits::can_insert_value_at_iterator_v>); static_assert(QContainerTraits::can_erase_at_iterator_v>); static_assert(QContainerTraits::can_erase_at_iterator_v>); @@ -172,10 +173,19 @@ private: std::set stdset; std::forward_list forwardList; + QHash qhash; + QMap qmap; + std::map stdmap; + std::unordered_map 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>(), QMetaSequence::fromContainer>() }; + qhash = { + { 233, QMetaType() }, + { 11, QMetaType::fromType() }, + { 6626, QMetaType::fromType() } + }; + qmap = { + { "eins", true }, + { "zwei", false }, + { "elfundvierzig", true } + }; + + stdmap = { + { QStringLiteral("dkdkdkd"), 58583 }, + { QStringLiteral("ooo30393"), 12 }, + { QStringLiteral("2dddd30393"), 999999 }, + }; + stdunorderedmap = { + { 11, QMetaAssociation::fromContainer>() }, + { 12, QMetaAssociation::fromContainer>() }, + { 393, QMetaAssociation::fromContainer>() }, + { 293, QMetaAssociation::fromContainer>() } + }; } 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("container"); + QTest::addColumn("metaAssociation"); + QTest::addColumn("keyType"); + QTest::addColumn("mappedType"); + QTest::addColumn("hasSize"); + QTest::addColumn("canRemove"); + QTest::addColumn("canSetMapped"); + QTest::addColumn("hasBidirectionalIterator"); + QTest::addColumn("hasRandomAccessIterator"); + + QTest::addRow("QHash") + << static_cast(&qhash) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << QMetaType::fromType() + << true << true << true << false << false; + QTest::addRow("QMap") + << static_cast(&qmap) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << QMetaType::fromType() + << true << true << true << true << false; + QTest::addRow("std::map") + << static_cast(&stdmap) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << QMetaType::fromType() + << true << true << true << true << false; + QTest::addRow("std::unorderedmap") + << static_cast(&stdunorderedmap) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << QMetaType::fromType() + << true << true << true << false << false; + QTest::addRow("QSet") + << static_cast(&qset) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << QMetaType() + << true << true << false << false << false; + QTest::addRow("std::set") + << static_cast(&stdset) + << QMetaAssociation::fromContainer>() + << QMetaType::fromType() + << 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(dataPtr) = mytype; }; - metaSequence.valueMetaType = QMetaType::fromType(); + metaSequence.valueMetaType = QtPrivate::qMetaTypeInterfaceForType(); QSequentialIterable iterable(QMetaSequence(&metaSequence), nullptr); QVariant value1 = iterable.at(0);