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>
This commit is contained in:
Ulf Hermann 2020-09-10 18:23:23 +02:00
parent d423fe9851
commit 1162b4bfc9
5 changed files with 1347 additions and 393 deletions

View File

@ -51,6 +51,12 @@ namespace QContainerTraits
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;
@ -61,6 +67,21 @@ using const_iterator = typename C::const_iterator;
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>
@ -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_v<C, std::void_t<decltype(C().at(0))>> = true;
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_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
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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::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_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_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_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::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"

View File

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