Revision control

++ // Copyright (C) 2020 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:significant reason:default
++
++ #ifndef QMETACONTAINER_H
++ #define QMETACONTAINER_H
++
++ #include <QtCore/qcontainerinfo.h>
++ #include <QtCore/qcompare.h>
++ #include <QtCore/qflags.h>
++ #include <QtCore/qglobal.h>
++
++ #include <iterator>
++
++ QT_BEGIN_NAMESPACE
++
++ class QMetaType;
++ namespace QtPrivate {
++ class QMetaTypeInterface;
++ template<typename T>
++ constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
++ }
++
++ namespace QtMetaContainerPrivate {
++
++ class Sequence;
++ class SequentialIterator;
++ class Association;
++ class AssociativeIterator;
++
++ enum IteratorCapability : quint8 {
++ InputCapability = 1 << 0,
++ ForwardCapability = 1 << 1,
++ BiDirectionalCapability = 1 << 2,
++ RandomAccessCapability = 1 << 3,
++ };
++
++ Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
++ Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
++
++ enum AddRemoveCapability : quint8 {
++ CanAddAtBegin = 1 << 0,
++ CanRemoveAtBegin = 1 << 1,
++ CanAddAtEnd = 1 << 2,
++ CanRemoveAtEnd = 1 << 3
++ };
++ Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
++ Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
++
++ class QMetaContainerInterface
++ {
++ public:
++ enum Position : quint8 { AtBegin, AtEnd, Unspecified };
++ ushort revision = 0;
++ IteratorCapabilities iteratorCapabilities;
++
++ using SizeFn = qsizetype(*)(const void *);
++ SizeFn sizeFn;
++ using ClearFn = void(*)(void *);
++ ClearFn clearFn;
++
++ using CreateIteratorFn = void *(*)(void *, Position);
++ CreateIteratorFn createIteratorFn;
++ using DestroyIteratorFn = void(*)(const void *);
++ DestroyIteratorFn destroyIteratorFn;
++ using CompareIteratorFn = bool(*)(const void *, const void *);
++ CompareIteratorFn compareIteratorFn;
++ using CopyIteratorFn = void(*)(void *, const void *);
++ CopyIteratorFn copyIteratorFn;
++ using AdvanceIteratorFn = void(*)(void *, qsizetype);
++ AdvanceIteratorFn advanceIteratorFn;
++ using DiffIteratorFn = qsizetype(*)(const void *, const void *);
++ DiffIteratorFn diffIteratorFn;
++
++ using CreateConstIteratorFn = void *(*)(const void *, Position);
++ CreateConstIteratorFn createConstIteratorFn;
++ DestroyIteratorFn destroyConstIteratorFn;
++ CompareIteratorFn compareConstIteratorFn;
++ CopyIteratorFn copyConstIteratorFn;
++ AdvanceIteratorFn advanceConstIteratorFn;
++ DiffIteratorFn diffConstIteratorFn;
++
++ QMetaContainerInterface() = default;
++
++ template<typename MetaContainer>
++ constexpr 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:
++ const 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<typename MetaSequence>
++ constexpr 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:
++ const QtPrivate::QMetaTypeInterface *keyMetaType;
++ const QtPrivate::QMetaTypeInterface *mappedMetaType;
++
++ using InsertKeyFn = void(*)(void *, const void *);
++ InsertKeyFn insertKeyFn;
++ using RemoveKeyFn = void(*)(void *, const void *);
++ RemoveKeyFn removeKeyFn;
++ using ContainsKeyFn = bool(*)(const void *, const void *);
++ ContainsKeyFn containsKeyFn;
++
++ using MappedAtKeyFn = void(*)(const void *, const void *, void *);
++ MappedAtKeyFn mappedAtKeyFn;
++ using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
++ SetMappedAtKeyFn setMappedAtKeyFn;
++
++ using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
++ CreateIteratorAtKeyFn createIteratorAtKeyFn;
++ using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
++ CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
++
++ using KeyAtIteratorFn = void(*)(const void *, void *);
++ KeyAtIteratorFn keyAtIteratorFn;
++ KeyAtIteratorFn keyAtConstIteratorFn;
++
++ using MappedAtIteratorFn = void(*)(const void *, void *);
++ MappedAtIteratorFn mappedAtIteratorFn;
++ MappedAtIteratorFn mappedAtConstIteratorFn;
++
++ using SetMappedAtIteratorFn = void(*)(const void *, const void *);
++ SetMappedAtIteratorFn setMappedAtIteratorFn;
++
++ using EraseKeyAtIteratorFn = void(*)(void *, const void *);
++ EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
++
++ QMetaAssociationInterface() = default;
++
++ template<typename MetaAssociation>
++ constexpr QMetaAssociationInterface(const MetaAssociation &m)
++ : QMetaContainerInterface(m)
++ , keyMetaType(MetaAssociation::getKeyMetaType())
++ , mappedMetaType(MetaAssociation::getMappedMetaType())
++ , insertKeyFn(MetaAssociation::getInsertKeyFn())
++ , removeKeyFn(MetaAssociation::getRemoveKeyFn())
++ , containsKeyFn(MetaAssociation::getContainsKeyFn())
++ , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
++ , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
++ , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
++ , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
++ , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
++ , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
++ , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
++ , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
++ , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
++ , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
++ {}
++ };
++
++ template<typename C>
++ class QMetaContainerForContainer
++ {
++ friend QMetaContainerInterface;
++
++ template <typename Iterator>
++ static constexpr IteratorCapabilities capabilitiesForIterator()
++ {
++ using Tag = typename std::iterator_traits<Iterator>::iterator_category;
++ IteratorCapabilities caps {};
++ if constexpr (std::is_base_of_v<std::input_iterator_tag, Tag>)
++ caps |= InputCapability;
++ if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
++ caps |= ForwardCapability;
++ if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
++ caps |= BiDirectionalCapability;
++ if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
++ caps |= RandomAccessCapability;
++ return caps;
++ }
++
++ static constexpr IteratorCapabilities getIteratorCapabilities()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>)
++ return capabilitiesForIterator<QContainerInfo::iterator<C>>();
++ else if constexpr (QContainerInfo::has_const_iterator_v<C>)
++ return capabilitiesForIterator<QContainerInfo::const_iterator<C>>();
++ else
++ return {};
++ }
++
++ static constexpr QMetaContainerInterface::SizeFn getSizeFn()
++ {
++ if constexpr (QContainerInfo::has_size_v<C>) {
++ return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::ClearFn getClearFn()
++ {
++ if constexpr (QContainerInfo::has_clear_v<C>) {
++ return [](void *c) { return static_cast<C *>(c)->clear(); };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *c, QMetaContainerInterface::Position p) -> void* {
++ using Iterator = QContainerInfo::iterator<C>;
++ switch (p) {
++ case QMetaContainerInterface::Unspecified:
++ return new Iterator;
++ case QMetaContainerInterface::AtBegin:
++ return new Iterator(static_cast<C *>(c)->begin());
++ case QMetaContainerInterface::AtEnd:
++ return new Iterator(static_cast<C *>(c)->end());
++ }
++ return nullptr;
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](const void *i) {
++ using Iterator = QContainerInfo::iterator<C>;
++ delete static_cast<const Iterator *>(i);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](const void *i, const void *j) {
++ using Iterator = QContainerInfo::iterator<C>;
++ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *i, const void *j) {
++ using Iterator = QContainerInfo::iterator<C>;
++ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *i, qsizetype step) {
++ std::advance(*static_cast<QContainerInfo::iterator<C> *>(i), step);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
++ return [](const void *i, const void *j) -> qsizetype {
++ return std::distance(*static_cast<const QContainerInfo::iterator<C> *>(j),
++ *static_cast<const QContainerInfo::iterator<C> *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](const void *c, QMetaContainerInterface::Position p) -> void* {
++ using Iterator = QContainerInfo::const_iterator<C>;
++ switch (p) {
++ case QMetaContainerInterface::Unspecified:
++ return new Iterator;
++ case QMetaContainerInterface::AtBegin:
++ return new Iterator(static_cast<const C *>(c)->begin());
++ case QMetaContainerInterface::AtEnd:
++ return new Iterator(static_cast<const C *>(c)->end());
++ }
++ return nullptr;
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](const void *i) {
++ using Iterator = QContainerInfo::const_iterator<C>;
++ delete static_cast<const Iterator *>(i);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](const void *i, const void *j) {
++ using Iterator = QContainerInfo::const_iterator<C>;
++ return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](void *i, const void *j) {
++ using Iterator = QContainerInfo::const_iterator<C>;
++ *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](void *i, qsizetype step) {
++ std::advance(*static_cast<QContainerInfo::const_iterator<C> *>(i), step);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>) {
++ return [](const void *i, const void *j) -> qsizetype {
++ return std::distance(*static_cast<const QContainerInfo::const_iterator<C> *>(j),
++ *static_cast<const QContainerInfo::const_iterator<C> *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ protected:
++
++ template<typename EraseFn>
++ static constexpr EraseFn getEraseAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C>
++ && QContainerInfo::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *c, const void *i) {
++ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++ };
++
++ template<typename C>
++ class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
++ {
++ friend QMetaSequenceInterface;
++
++ static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
++ {
++ if constexpr (QContainerInfo::has_value_type_v<C>)
++ return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
++ else
++ return nullptr;
++ }
++
++ static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
++ {
++ AddRemoveCapabilities caps;
++ if constexpr (QContainerInfo::has_push_back_v<C>)
++ caps |= CanAddAtEnd;
++ if constexpr (QContainerInfo::has_pop_back_v<C>)
++ caps |= CanRemoveAtEnd;
++ if constexpr (QContainerInfo::has_push_front_v<C>)
++ caps |= CanAddAtBegin;
++ if constexpr (QContainerInfo::has_pop_front_v<C>)
++ caps |= CanRemoveAtBegin;
++ return caps;
++ }
++
++ static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
++ {
++ if constexpr (QContainerInfo::has_at_index_v<C>) {
++ return [](const void *c, qsizetype i, void *r) {
++ *static_cast<QContainerInfo::value_type<C> *>(r)
++ = static_cast<const C *>(c)->at(i);
++ };
++ } else if constexpr (QContainerInfo::can_get_at_index_v<C>) {
++ return [](const void *c, qsizetype i, void *r) {
++ *static_cast<QContainerInfo::value_type<C> *>(r)
++ = (*static_cast<const C *>(c))[i];
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn()
++ {
++ if constexpr (QContainerInfo::can_set_at_index_v<C>) {
++ return [](void *c, qsizetype i, const void *e) {
++ (*static_cast<C *>(c))[i]
++ = *static_cast<const QContainerInfo::value_type<C> *>(e);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
++ {
++ if constexpr (QContainerInfo::has_push_back_v<C>) {
++ if constexpr (QContainerInfo::has_push_front_v<C>) {
++ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
++ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
++ switch (position) {
++ case QMetaSequenceInterface::AtBegin:
++ static_cast<C *>(c)->push_front(value);
++ break;
++ case QMetaSequenceInterface::AtEnd:
++ case QMetaSequenceInterface::Unspecified:
++ static_cast<C *>(c)->push_back(value);
++ break;
++ }
++ };
++ } else {
++ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
++ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
++ switch (position) {
++ case QMetaSequenceInterface::AtBegin:
++ break;
++ case QMetaSequenceInterface::AtEnd:
++ case QMetaSequenceInterface::Unspecified:
++ static_cast<C *>(c)->push_back(value);
++ break;
++ }
++ };
++ }
++ } else if constexpr (QContainerInfo::has_push_front_v<C>) {
++ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
++ const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
++ switch (position) {
++ case QMetaSequenceInterface::Unspecified:
++ case QMetaSequenceInterface::AtBegin:
++ static_cast<C *>(c)->push_front(value);
++ case QMetaSequenceInterface::AtEnd:
++ break;
++ }
++ };
++ } else if constexpr (QContainerInfo::has_insert_v<C>) {
++ return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
++ if (position == QMetaSequenceInterface::Unspecified) {
++ static_cast<C *>(c)->insert(
++ *static_cast<const QContainerInfo::value_type<C> *>(v));
++ }
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
++ {
++ if constexpr (QContainerInfo::has_pop_back_v<C>) {
++ if constexpr (QContainerInfo::has_pop_front_v<C>) {
++ return [](void *c, QMetaSequenceInterface::Position position) {
++ switch (position) {
++ case QMetaSequenceInterface::AtBegin:
++ static_cast<C *>(c)->pop_front();
++ break;
++ case QMetaSequenceInterface::AtEnd:
++ case QMetaSequenceInterface::Unspecified:
++ static_cast<C *>(c)->pop_back();
++ break;
++ }
++ };
++ } else {
++ return [](void *c, QMetaSequenceInterface::Position position) {
++ switch (position) {
++ case QMetaSequenceInterface::AtBegin:
++ break;
++ case QMetaSequenceInterface::Unspecified:
++ case QMetaSequenceInterface::AtEnd:
++ static_cast<C *>(c)->pop_back();
++ break;
++ }
++ };
++ }
++ } else if constexpr (QContainerInfo::has_pop_front_v<C>) {
++ return [](void *c, QMetaSequenceInterface::Position position) {
++ switch (position) {
++ case QMetaSequenceInterface::Unspecified:
++ case QMetaSequenceInterface::AtBegin:
++ static_cast<C *>(c)->pop_front();
++ break;
++ case QMetaSequenceInterface::AtEnd:
++ break;
++ }
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C>
++ && QContainerInfo::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
++ return [](const void *i, void *r) {
++ *static_cast<QContainerInfo::value_type<C> *>(r) =
++ *(*static_cast<const QContainerInfo::iterator<C> *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C>
++ && QContainerInfo::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
++ return [](const void *i, const void *e) {
++ *(*static_cast<const QContainerInfo::iterator<C> *>(i))
++ = *static_cast<const QContainerInfo::value_type<C> *>(e);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C>
++ && QContainerInfo::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *c, const void *i, const void *e) {
++ static_cast<C *>(c)->insert(
++ *static_cast<const QContainerInfo::iterator<C> *>(i),
++ *static_cast<const QContainerInfo::value_type<C> *>(e));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_const_iterator_v<C>
++ && QContainerInfo::iterator_dereferences_to_value_v<C>) {
++ return [](const void *i, void *r) {
++ *static_cast<QContainerInfo::value_type<C> *>(r) =
++ *(*static_cast<const QContainerInfo::const_iterator<C> *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
++ {
++ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
++ QMetaSequenceInterface::EraseValueAtIteratorFn>();
++ }
++
++ static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::has_iterator_v<C>
++ && QContainerInfo::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
++ return [](void *c, const void *i, const void *j) {
++ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i),
++ *static_cast<const QContainerInfo::iterator<C> *>(j));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++ };
++
++ template<typename C>
++ class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
++ {
++ friend QMetaAssociationInterface;
++
++ static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
++ {
++ if constexpr (QContainerInfo::has_key_type_v<C>)
++ return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
++ else
++ return nullptr;
++ }
++
++ static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
++ {
++ if constexpr (QContainerInfo::has_mapped_type_v<C>)
++ return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
++ else
++ return nullptr;
++ }
++
++ static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
++ {
++ if constexpr (QContainerInfo::can_insert_key_v<C>) {
++ return [](void *c, const void *k) {
++ static_cast<C *>(c)->insert(
++ *static_cast<const QContainerInfo::key_type<C> *>(k));
++ };
++ } else if constexpr (QContainerInfo::can_insert_pair_v<C>) {
++ return [](void *c, const void *k) {
++ static_cast<C *>(c)->insert(
++ {*static_cast<const QContainerInfo::key_type<C> *>(k), {}});
++ };
++ } else if constexpr (QContainerInfo::can_insert_key_mapped_v<C>) {
++ return [](void *c, const void *k) {
++ static_cast<C *>(c)->insert(
++ *static_cast<const QContainerInfo::key_type<C> *>(k), {});
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
++ {
++ if constexpr (QContainerInfo::can_erase_at_key_v<C>) {
++ return [](void *c, const void *k) {
++ static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::key_type<C> *>(k));
++ };
++ } else if constexpr (QContainerInfo::can_remove_at_key_v<C>) {
++ return [](void *c, const void *k) {
++ static_cast<C *>(c)->remove(*static_cast<const QContainerInfo::key_type<C> *>(k));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
++ {
++ if constexpr (QContainerInfo::has_contains_v<C>) {
++ return [](const void *c, const void *k) {
++ return static_cast<const C *>(c)->contains(
++ *static_cast<const QContainerInfo::key_type<C> *>(k));
++ };
++ } else if (QContainerInfo::has_find_v<C>) {
++ return [](const void *c, const void *k) {
++ const C *container = static_cast<const C *>(c);
++ return container->find(
++ *static_cast<const QContainerInfo::key_type<C> *>(k))
++ != container->end();
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
++ {
++ if constexpr (QContainerInfo::has_at_key_v<C>) {
++ return [](const void *c, const void *k, void *r) {
++ *static_cast<QContainerInfo::mapped_type<C> *>(r)
++ = static_cast<const C *>(c)->at(
++ *static_cast<const QContainerInfo::key_type<C> *>(k));
++ };
++ } else if constexpr (QContainerInfo::can_get_at_key_v<C>) {
++ return [](const void *c, const void *k, void *r) {
++ *static_cast<QContainerInfo::mapped_type<C> *>(r)
++ = (*static_cast<const C *>(c))[
++ *static_cast<const QContainerInfo::key_type<C> *>(k)];
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
++ {
++ if constexpr (QContainerInfo::can_set_at_key_v<C>) {
++ return [](void *c, const void *k, const void *m) {
++ (*static_cast<C *>(c))[*static_cast<const QContainerInfo::key_type<C> *>(k)] =
++ *static_cast<const QContainerInfo::mapped_type<C> *>(m);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
++ {
++ if constexpr (QContainerInfo::has_find_v<C>) {
++ return [](void *c, const void *k) -> void* {
++ using Iterator = QContainerInfo::iterator<C>;
++ return new Iterator(static_cast<C *>(c)->find(
++ *static_cast<const QContainerInfo::key_type<C> *>(k)));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
++ {
++ if constexpr (QContainerInfo::has_find_v<C>) {
++ return [](const void *c, const void *k) -> void* {
++ using Iterator = QContainerInfo::const_iterator<C>;
++ return new Iterator(static_cast<const C *>(c)->find(
++ *static_cast<const QContainerInfo::key_type<C> *>(k)));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ template<typename Iterator>
++ static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::iterator_has_key_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::key_type<C> *>(k)
++ = static_cast<const Iterator *>(i)->key();
++ };
++ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
++ && QContainerInfo::value_type_has_first_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::key_type<C> *>(k)
++ = (*static_cast<const Iterator *>(i))->first;
++ };
++ } else if constexpr (QContainerInfo::iterator_dereferences_to_key_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::key_type<C> *>(k)
++ = *(*static_cast<const Iterator *>(i));
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
++ {
++ return keyAtIteratorFn<QContainerInfo::iterator<C>>();
++ }
++
++ static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
++ {
++ return keyAtIteratorFn<QContainerInfo::const_iterator<C>>();
++ }
++
++ template<typename Iterator>
++ static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::iterator_has_value_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::mapped_type<C> *>(k)
++ = static_cast<const Iterator *>(i)->value();
++ };
++ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
++ && QContainerInfo::value_type_has_second_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::mapped_type<C> *>(k)
++ = (*static_cast<const Iterator *>(i))->second;
++ };
++ } else if constexpr (QContainerInfo::iterator_dereferences_to_mapped_v<C>) {
++ return [](const void *i, void *k) {
++ *static_cast<QContainerInfo::mapped_type<C> *>(k)
++ = *static_cast<const Iterator *>(i);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
++ {
++ return mappedAtIteratorFn<QContainerInfo::iterator<C>>();
++ }
++
++ static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
++ {
++ return mappedAtIteratorFn<QContainerInfo::const_iterator<C>>();
++ }
++
++ static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
++ {
++ if constexpr (QContainerInfo::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
++ return [](const void *i, const void *m) {
++ *(*static_cast<const QContainerInfo::iterator<C> *>(i))
++ = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
++ };
++ } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
++ && QContainerInfo::value_type_has_second_v<C>) {
++ return [](const void *i, const void *m) {
++ (*static_cast<const QContainerInfo::iterator<C> *>(i))->second
++ = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
++ };
++ } else {
++ return nullptr;
++ }
++ }
++
++ static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
++ {
++ return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
++ QMetaAssociationInterface::EraseKeyAtIteratorFn>();
++ }
++ };
++
++ } // namespace QtMetaContainerPrivate
++
++ 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;
++ };
++
++ // ### Qt7: Move this to qmetasequence.h, including QtMetaContainerPrivate parts above.
++ class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
++ {
++ public:
++ #ifdef Q_QDOC
++ class Iterable : public QIterable<QMetaSequence>
++ {
++ public:
++ class Iterator : public QIterator<QMetaSequence>
++ {
++ public:
++ QVariant::Reference<Iterator> operator*() const;
++ QVariant::Pointer<Iterator> operator->() const;
++ QVariant::Reference<Iterator> operator[](qsizetype n) const;
++ };
++
++ class ConstIterator : public QConstIterator<QMetaSequence>
++ {
++ public:
++ QVariant operator*() const;
++ QVariant::ConstPointer<ConstIterator> operator->() const;
++ QVariant operator[](qsizetype n) const;
++ };
++
++ using RandomAccessIterator = Iterator;
++ using BidirectionalIterator = Iterator;
++ using ForwardIterator = Iterator;
++ using InputIterator = Iterator;
++
++ using RandomAccessConstIterator = ConstIterator;
++ using BidirectionalConstIterator = ConstIterator;
++ using ForwardConstIterator = ConstIterator;
++ using InputConstIterator = ConstIterator;
++
++ ConstIterator begin() const;
++ ConstIterator end() const;
++
++ ConstIterator constBegin() const;
++ ConstIterator constEnd() const;
++
++ Iterator mutableBegin();
++ Iterator mutableEnd();
++
++ QVariant at(qsizetype idx) const;
++ void setAt(qsizetype idx, const QVariant &value);
++ void append(const QVariant &value);
++ void prepend(const QVariant &value);
++ void removeLast();
++ void removeFirst();
++ };
++ #else
++ using Iterable = QtMetaContainerPrivate::Sequence;
++ #endif
++
++ QMetaSequence() = default;
++ explicit QMetaSequence(const QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
++
++ template<typename T>
++ static constexpr QMetaSequence fromContainer()
++ {
++ return QMetaSequence(&MetaSequence<T>::value);
++ }
++
++ QMetaType valueMetaType() const;
++
++ bool isSortable() const;
++ bool canAddValueAtBegin() const;
++ void addValueAtBegin(void *container, const void *value) const;
++ bool canAddValueAtEnd() const;
++ void addValueAtEnd(void *container, const void *value) const;
++ bool canRemoveValueAtBegin() const;
++ void removeValueAtBegin(void *container) const;
++ bool canRemoveValueAtEnd() const;
++ void removeValueAtEnd(void *container) const;
++
++ bool canGetValueAtIndex() const;
++ void valueAtIndex(const void *container, qsizetype index, void *result) const;
++
++ bool canSetValueAtIndex() const;
++ void setValueAtIndex(void *container, qsizetype index, const void *value) const;
++
++ bool canAddValue() const;
++ void addValue(void *container, const void *value) const;
++
++ bool canRemoveValue() const;
++ void removeValue(void *container) const;
++
++ bool canGetValueAtIterator() const;
++ void valueAtIterator(const void *iterator, void *result) const;
++
++ bool canSetValueAtIterator() const;
++ void setValueAtIterator(const void *iterator, const void *value) const;
++
++ bool canInsertValueAtIterator() const;
++ void insertValueAtIterator(void *container, const void *iterator, const void *value) const;
++
++ bool canEraseValueAtIterator() const;
++ void eraseValueAtIterator(void *container, const void *iterator) const;
++
++ bool canEraseRangeAtIterator() const;
++ void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
++
++ bool canGetValueAtConstIterator() const;
++ void valueAtConstIterator(const void *iterator, void *result) const;
++
++ const QtMetaContainerPrivate::QMetaSequenceInterface *iface() const { return d(); }
++
++ private:
++ friend bool comparesEqual(const QMetaSequence &lhs, const QMetaSequence &rhs) noexcept
++ {
++ return lhs.d() == rhs.d();
++ }
++ Q_DECLARE_EQUALITY_COMPARABLE(QMetaSequence)
++
++ template<typename T>
++ struct MetaSequence
++ {
++ static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value
++ = QtMetaContainerPrivate::QMetaSequenceInterface(
++ QtMetaContainerPrivate::QMetaSequenceForContainer<T>());
++ };
++
++ const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
++ {
++ return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
++ }
++ };
++
++ // ### Qt7: Move this to qmetaassociation.h, including QtMetaContainerPrivate parts above.
++ class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
++ {
++ public:
++ #ifdef Q_QDOC
++ class Iterable : public QIterable<QMetaAssociation>
++ {
++ public:
++ class Iterator : public QIterator<QMetaAssociation>
++ {
++ public:
++ QVariant key() const;
++ QVariant value() const;
++
++ QVariant::Reference<Iterator> operator*() const;
++ QVariant::Pointer<Iterator> operator->() const;
++ };
++
++ class ConstIterator : public QConstIterator<QMetaAssociation>
++ {
++ public:
++ QVariant key() const;
++ QVariant value() const;
++
++ QVariant operator*() const;
++ QVariant::ConstPointer<ConstIterator> operator->() const;
++ };
++
++ using RandomAccessIterator = Iterator;
++ using BidirectionalIterator = Iterator;
++ using ForwardIterator = Iterator;
++ using InputIterator = Iterator;
++
++ using RandomAccessConstIterator = ConstIterator;
++ using BidirectionalConstIterator = ConstIterator;
++ using ForwardConstIterator = ConstIterator;
++ using InputConstIterator = ConstIterator;
++
++ ConstIterator begin() const;
++ ConstIterator end() const;
++
++ ConstIterator constBegin() const;
++ ConstIterator constEnd() const;
++
++ Iterator mutableBegin();
++ Iterator mutableEnd();
++
++ ConstIterator find(const QVariant &key) const;
++ ConstIterator constFind(const QVariant &key) const;
++ Iterator mutableFind(const QVariant &key);
++
++ bool containsKey(const QVariant &key) const;
++ void insertKey(const QVariant &key);
++ void removeKey(const QVariant &key);
++ QVariant value(const QVariant &key) const;
++ void setValue(const QVariant &key, const QVariant &mapped);
++ };
++ #else
++ using Iterable = QtMetaContainerPrivate::Association;
++ #endif
++
++ QMetaAssociation() = default;
++ explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
++
++ template<typename T>
++ static constexpr QMetaAssociation fromContainer()
++ {
++ return QMetaAssociation(&MetaAssociation<T>::value);
++ }
++
++ 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;
++ }
++
++ const QtMetaContainerPrivate::QMetaAssociationInterface *iface() const { return d(); }
++
++ private:
++ friend bool comparesEqual(const QMetaAssociation &lhs, const QMetaAssociation &rhs) noexcept
++ {
++ return lhs.d() == rhs.d();
++ }
++ Q_DECLARE_EQUALITY_COMPARABLE(QMetaAssociation)
++
++ template<typename T>
++ struct MetaAssociation
++ {
++ static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value
++ = QtMetaContainerPrivate::QMetaAssociationInterface(
++ QtMetaContainerPrivate::QMetaAssociationForContainer<T>());
++ };
++
++ const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
++ {
++ return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
++ }
++ };
++
++ QT_END_NAMESPACE
++
++ #endif // QMETACONTAINER_H