Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:24:21

0001 // Copyright (C) 2020 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QMETACONTAINER_H
0005 #define QMETACONTAINER_H
0006 
0007 #include <QtCore/qcontainerinfo.h>
0008 #include <QtCore/qcompare.h>
0009 #include <QtCore/qflags.h>
0010 #include <QtCore/qglobal.h>
0011 
0012 #include <iterator>
0013 
0014 QT_BEGIN_NAMESPACE
0015 
0016 class QMetaType;
0017 namespace QtPrivate {
0018 class QMetaTypeInterface;
0019 template<typename T>
0020 constexpr const QMetaTypeInterface *qMetaTypeInterfaceForType();
0021 }
0022 
0023 namespace QtMetaContainerPrivate {
0024 
0025 enum IteratorCapability : quint8 {
0026     InputCapability         = 1 << 0,
0027     ForwardCapability       = 1 << 1,
0028     BiDirectionalCapability = 1 << 2,
0029     RandomAccessCapability  = 1 << 3,
0030 };
0031 
0032 Q_DECLARE_FLAGS(IteratorCapabilities, IteratorCapability)
0033 Q_DECLARE_OPERATORS_FOR_FLAGS(IteratorCapabilities)
0034 
0035 enum AddRemoveCapability : quint8 {
0036     CanAddAtBegin    = 1 << 0,
0037     CanRemoveAtBegin = 1 << 1,
0038     CanAddAtEnd      = 1 << 2,
0039     CanRemoveAtEnd   = 1 << 3
0040 };
0041 Q_DECLARE_FLAGS(AddRemoveCapabilities, AddRemoveCapability)
0042 Q_DECLARE_OPERATORS_FOR_FLAGS(AddRemoveCapabilities)
0043 
0044 class QMetaContainerInterface
0045 {
0046 public:
0047     enum Position : quint8 { AtBegin, AtEnd, Unspecified };
0048     ushort revision = 0;
0049     IteratorCapabilities iteratorCapabilities;
0050 
0051     using SizeFn = qsizetype(*)(const void *);
0052     SizeFn sizeFn;
0053     using ClearFn = void(*)(void *);
0054     ClearFn clearFn;
0055 
0056     using CreateIteratorFn = void *(*)(void *, Position);
0057     CreateIteratorFn createIteratorFn;
0058     using DestroyIteratorFn = void(*)(const void *);
0059     DestroyIteratorFn destroyIteratorFn;
0060     using CompareIteratorFn = bool(*)(const void *, const void *);
0061     CompareIteratorFn compareIteratorFn;
0062     using CopyIteratorFn = void(*)(void *, const void *);
0063     CopyIteratorFn copyIteratorFn;
0064     using AdvanceIteratorFn = void(*)(void *, qsizetype);
0065     AdvanceIteratorFn advanceIteratorFn;
0066     using DiffIteratorFn = qsizetype(*)(const void *, const void *);
0067     DiffIteratorFn diffIteratorFn;
0068 
0069     using CreateConstIteratorFn = void *(*)(const void *, Position);
0070     CreateConstIteratorFn createConstIteratorFn;
0071     DestroyIteratorFn destroyConstIteratorFn;
0072     CompareIteratorFn compareConstIteratorFn;
0073     CopyIteratorFn copyConstIteratorFn;
0074     AdvanceIteratorFn advanceConstIteratorFn;
0075     DiffIteratorFn diffConstIteratorFn;
0076 
0077     QMetaContainerInterface() = default;
0078 
0079     template<typename MetaContainer>
0080     constexpr QMetaContainerInterface(const MetaContainer &)
0081         : iteratorCapabilities(MetaContainer::getIteratorCapabilities())
0082         , sizeFn(MetaContainer::getSizeFn())
0083         , clearFn(MetaContainer::getClearFn())
0084         , createIteratorFn(MetaContainer::getCreateIteratorFn())
0085         , destroyIteratorFn(MetaContainer::getDestroyIteratorFn())
0086         , compareIteratorFn(MetaContainer::getCompareIteratorFn())
0087         , copyIteratorFn(MetaContainer::getCopyIteratorFn())
0088         , advanceIteratorFn(MetaContainer::getAdvanceIteratorFn())
0089         , diffIteratorFn(MetaContainer::getDiffIteratorFn())
0090         , createConstIteratorFn(MetaContainer::getCreateConstIteratorFn())
0091         , destroyConstIteratorFn(MetaContainer::getDestroyConstIteratorFn())
0092         , compareConstIteratorFn(MetaContainer::getCompareConstIteratorFn())
0093         , copyConstIteratorFn(MetaContainer::getCopyConstIteratorFn())
0094         , advanceConstIteratorFn(MetaContainer::getAdvanceConstIteratorFn())
0095         , diffConstIteratorFn(MetaContainer::getDiffConstIteratorFn())
0096     {}
0097 };
0098 
0099 class QMetaSequenceInterface : public QMetaContainerInterface
0100 {
0101 public:
0102     const QtPrivate::QMetaTypeInterface *valueMetaType;
0103     AddRemoveCapabilities addRemoveCapabilities;
0104 
0105     using ValueAtIndexFn = void(*)(const void *, qsizetype, void *);
0106     ValueAtIndexFn valueAtIndexFn;
0107     using SetValueAtIndexFn = void(*)(void *, qsizetype, const void *);
0108     SetValueAtIndexFn setValueAtIndexFn;
0109 
0110     using AddValueFn = void(*)(void *, const void *, Position);
0111     AddValueFn addValueFn;
0112     using RemoveValueFn = void(*)(void *, Position);
0113     RemoveValueFn removeValueFn;
0114 
0115     using ValueAtIteratorFn = void(*)(const void *, void *);
0116     ValueAtIteratorFn valueAtIteratorFn;
0117     using SetValueAtIteratorFn = void(*)(const void *, const void *);
0118     SetValueAtIteratorFn setValueAtIteratorFn;
0119     using InsertValueAtIteratorFn = void(*)(void *, const void *, const void *);
0120     InsertValueAtIteratorFn insertValueAtIteratorFn;
0121 
0122     ValueAtIteratorFn valueAtConstIteratorFn;
0123 
0124     using EraseValueAtIteratorFn = void(*)(void *, const void *);
0125     EraseValueAtIteratorFn eraseValueAtIteratorFn;
0126 
0127     using EraseRangeAtIteratorFn = void(*)(void *, const void *, const void *);
0128     EraseRangeAtIteratorFn eraseRangeAtIteratorFn;
0129 
0130     QMetaSequenceInterface() = default;
0131 
0132     template<typename MetaSequence>
0133     constexpr QMetaSequenceInterface(const MetaSequence &m)
0134         : QMetaContainerInterface(m)
0135         , valueMetaType(MetaSequence::getValueMetaType())
0136         , addRemoveCapabilities(MetaSequence::getAddRemoveCapabilities())
0137         , valueAtIndexFn(MetaSequence::getValueAtIndexFn())
0138         , setValueAtIndexFn(MetaSequence::getSetValueAtIndexFn())
0139         , addValueFn(MetaSequence::getAddValueFn())
0140         , removeValueFn(MetaSequence::getRemoveValueFn())
0141         , valueAtIteratorFn(MetaSequence::getValueAtIteratorFn())
0142         , setValueAtIteratorFn(MetaSequence::getSetValueAtIteratorFn())
0143         , insertValueAtIteratorFn(MetaSequence::getInsertValueAtIteratorFn())
0144         , valueAtConstIteratorFn(MetaSequence::getValueAtConstIteratorFn())
0145         , eraseValueAtIteratorFn(MetaSequence::getEraseValueAtIteratorFn())
0146         , eraseRangeAtIteratorFn(MetaSequence::getEraseRangeAtIteratorFn())
0147     {}
0148 };
0149 
0150 class QMetaAssociationInterface : public QMetaContainerInterface
0151 {
0152 public:
0153     const QtPrivate::QMetaTypeInterface *keyMetaType;
0154     const QtPrivate::QMetaTypeInterface *mappedMetaType;
0155 
0156     using InsertKeyFn = void(*)(void *, const void *);
0157     InsertKeyFn insertKeyFn;
0158     using RemoveKeyFn = void(*)(void *, const void *);
0159     RemoveKeyFn removeKeyFn;
0160     using ContainsKeyFn = bool(*)(const void *, const void *);
0161     ContainsKeyFn containsKeyFn;
0162 
0163     using MappedAtKeyFn = void(*)(const void *, const void *, void *);
0164     MappedAtKeyFn mappedAtKeyFn;
0165     using SetMappedAtKeyFn = void(*)(void *, const void *, const void *);
0166     SetMappedAtKeyFn setMappedAtKeyFn;
0167 
0168     using CreateIteratorAtKeyFn = void *(*)(void *, const void *);
0169     CreateIteratorAtKeyFn createIteratorAtKeyFn;
0170     using CreateConstIteratorAtKeyFn = void *(*)(const void *, const void *);
0171     CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn;
0172 
0173     using KeyAtIteratorFn = void(*)(const void *, void *);
0174     KeyAtIteratorFn keyAtIteratorFn;
0175     KeyAtIteratorFn keyAtConstIteratorFn;
0176 
0177     using MappedAtIteratorFn = void(*)(const void *, void *);
0178     MappedAtIteratorFn mappedAtIteratorFn;
0179     MappedAtIteratorFn mappedAtConstIteratorFn;
0180 
0181     using SetMappedAtIteratorFn = void(*)(const void *, const void *);
0182     SetMappedAtIteratorFn setMappedAtIteratorFn;
0183 
0184     using EraseKeyAtIteratorFn = void(*)(void *, const void *);
0185     EraseKeyAtIteratorFn eraseKeyAtIteratorFn;
0186 
0187     QMetaAssociationInterface() = default;
0188 
0189     template<typename MetaAssociation>
0190     constexpr QMetaAssociationInterface(const MetaAssociation &m)
0191         : QMetaContainerInterface(m)
0192         , keyMetaType(MetaAssociation::getKeyMetaType())
0193         , mappedMetaType(MetaAssociation::getMappedMetaType())
0194         , insertKeyFn(MetaAssociation::getInsertKeyFn())
0195         , removeKeyFn(MetaAssociation::getRemoveKeyFn())
0196         , containsKeyFn(MetaAssociation::getContainsKeyFn())
0197         , mappedAtKeyFn(MetaAssociation::getMappedAtKeyFn())
0198         , setMappedAtKeyFn(MetaAssociation::getSetMappedAtKeyFn())
0199         , createIteratorAtKeyFn(MetaAssociation::createIteratorAtKeyFn())
0200         , createConstIteratorAtKeyFn(MetaAssociation::createConstIteratorAtKeyFn())
0201         , keyAtIteratorFn(MetaAssociation::getKeyAtIteratorFn())
0202         , keyAtConstIteratorFn(MetaAssociation::getKeyAtConstIteratorFn())
0203         , mappedAtIteratorFn(MetaAssociation::getMappedAtIteratorFn())
0204         , mappedAtConstIteratorFn(MetaAssociation::getMappedAtConstIteratorFn())
0205         , setMappedAtIteratorFn(MetaAssociation::getSetMappedAtIteratorFn())
0206         , eraseKeyAtIteratorFn(MetaAssociation::getEraseKeyAtIteratorFn())
0207     {}
0208 };
0209 
0210 template<typename C>
0211 class QMetaContainerForContainer
0212 {
0213     friend QMetaContainerInterface;
0214 
0215     template <typename Iterator>
0216     static constexpr IteratorCapabilities capabilitiesForIterator()
0217     {
0218        using Tag = typename std::iterator_traits<Iterator>::iterator_category;
0219        IteratorCapabilities caps {};
0220        if constexpr (std::is_base_of_v<std::input_iterator_tag, Tag>)
0221            caps |= InputCapability;
0222        if constexpr (std::is_base_of_v<std::forward_iterator_tag, Tag>)
0223            caps |= ForwardCapability;
0224        if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, Tag>)
0225            caps |= BiDirectionalCapability;
0226        if constexpr (std::is_base_of_v<std::random_access_iterator_tag, Tag>)
0227            caps |= RandomAccessCapability;
0228        return caps;
0229     }
0230 
0231     static constexpr IteratorCapabilities getIteratorCapabilities()
0232     {
0233         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>)
0234             return capabilitiesForIterator<QContainerInfo::iterator<C>>();
0235         else if constexpr (QContainerInfo::has_const_iterator_v<C>)
0236             return capabilitiesForIterator<QContainerInfo::const_iterator<C>>();
0237         else
0238             return {};
0239     }
0240 
0241     static constexpr QMetaContainerInterface::SizeFn getSizeFn()
0242     {
0243         if constexpr (QContainerInfo::has_size_v<C>) {
0244             return [](const void *c) -> qsizetype { return static_cast<const C *>(c)->size(); };
0245         } else {
0246             return nullptr;
0247         }
0248     }
0249 
0250     static constexpr QMetaContainerInterface::ClearFn getClearFn()
0251     {
0252         if constexpr (QContainerInfo::has_clear_v<C>) {
0253             return [](void *c) { return static_cast<C *>(c)->clear(); };
0254         } else {
0255             return nullptr;
0256         }
0257     }
0258 
0259     static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn()
0260     {
0261         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0262             return [](void *c, QMetaContainerInterface::Position p) -> void* {
0263                 using Iterator = QContainerInfo::iterator<C>;
0264                 switch (p) {
0265                 case QMetaContainerInterface::Unspecified:
0266                     return new Iterator;
0267                 case QMetaContainerInterface::AtBegin:
0268                     return new Iterator(static_cast<C *>(c)->begin());
0269                 case QMetaContainerInterface::AtEnd:
0270                     return new Iterator(static_cast<C *>(c)->end());
0271                 }
0272                 return nullptr;
0273             };
0274         } else {
0275             return nullptr;
0276         }
0277     }
0278 
0279     static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn()
0280     {
0281         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0282             return [](const void *i) {
0283                 using Iterator = QContainerInfo::iterator<C>;
0284                 delete static_cast<const Iterator *>(i);
0285             };
0286         } else {
0287             return nullptr;
0288         }
0289     }
0290 
0291     static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn()
0292     {
0293         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0294             return [](const void *i, const void *j) {
0295                 using Iterator = QContainerInfo::iterator<C>;
0296                 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
0297             };
0298         } else {
0299             return nullptr;
0300         }
0301     }
0302 
0303     static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn()
0304     {
0305         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0306             return [](void *i, const void *j) {
0307                 using Iterator = QContainerInfo::iterator<C>;
0308                 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
0309             };
0310         } else {
0311             return nullptr;
0312         }
0313     }
0314 
0315     static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn()
0316     {
0317         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0318             return [](void *i, qsizetype step) {
0319                 std::advance(*static_cast<QContainerInfo::iterator<C> *>(i), step);
0320             };
0321         } else {
0322             return nullptr;
0323         }
0324     }
0325 
0326     static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn()
0327     {
0328         if constexpr (QContainerInfo::has_iterator_v<C> && !std::is_const_v<C>) {
0329             return [](const void *i, const void *j) -> qsizetype {
0330                 return std::distance(*static_cast<const QContainerInfo::iterator<C> *>(j),
0331                                      *static_cast<const QContainerInfo::iterator<C> *>(i));
0332             };
0333         } else {
0334             return nullptr;
0335         }
0336     }
0337 
0338     static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn()
0339     {
0340         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0341             return [](const void *c, QMetaContainerInterface::Position p) -> void* {
0342                 using Iterator = QContainerInfo::const_iterator<C>;
0343                 switch (p) {
0344                 case QMetaContainerInterface::Unspecified:
0345                     return new Iterator;
0346                 case QMetaContainerInterface::AtBegin:
0347                     return new Iterator(static_cast<const C *>(c)->begin());
0348                 case QMetaContainerInterface::AtEnd:
0349                     return new Iterator(static_cast<const C *>(c)->end());
0350                 }
0351                 return nullptr;
0352             };
0353         } else {
0354             return nullptr;
0355         }
0356     }
0357 
0358     static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn()
0359     {
0360         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0361             return [](const void *i) {
0362                 using Iterator = QContainerInfo::const_iterator<C>;
0363                 delete static_cast<const Iterator *>(i);
0364             };
0365         } else {
0366             return nullptr;
0367         }
0368     }
0369 
0370     static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn()
0371     {
0372         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0373             return [](const void *i, const void *j) {
0374                 using Iterator = QContainerInfo::const_iterator<C>;
0375                 return *static_cast<const Iterator *>(i) == *static_cast<const Iterator *>(j);
0376             };
0377         } else {
0378             return nullptr;
0379         }
0380     }
0381 
0382     static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn()
0383     {
0384         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0385             return [](void *i, const void *j) {
0386                 using Iterator = QContainerInfo::const_iterator<C>;
0387                 *static_cast<Iterator *>(i) = *static_cast<const Iterator *>(j);
0388             };
0389         } else {
0390             return nullptr;
0391         }
0392     }
0393 
0394     static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn()
0395     {
0396         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0397             return [](void *i, qsizetype step) {
0398                 std::advance(*static_cast<QContainerInfo::const_iterator<C> *>(i), step);
0399             };
0400         } else {
0401             return nullptr;
0402         }
0403     }
0404 
0405     static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn()
0406     {
0407         if constexpr (QContainerInfo::has_const_iterator_v<C>) {
0408             return [](const void *i, const void *j) -> qsizetype {
0409                 return std::distance(*static_cast<const QContainerInfo::const_iterator<C> *>(j),
0410                                      *static_cast<const QContainerInfo::const_iterator<C> *>(i));
0411             };
0412         } else {
0413             return nullptr;
0414         }
0415     }
0416 
0417 protected:
0418 
0419     template<typename EraseFn>
0420     static constexpr EraseFn getEraseAtIteratorFn()
0421     {
0422         if constexpr (QContainerInfo::has_iterator_v<C>
0423                 && QContainerInfo::can_erase_at_iterator_v<C> && !std::is_const_v<C>) {
0424             return [](void *c, const void *i) {
0425                 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i));
0426             };
0427         } else {
0428             return nullptr;
0429         }
0430     }
0431 };
0432 
0433 template<typename C>
0434 class QMetaSequenceForContainer : public QMetaContainerForContainer<C>
0435 {
0436     friend QMetaSequenceInterface;
0437 
0438     static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType()
0439     {
0440         if constexpr (QContainerInfo::has_value_type_v<C>)
0441             return QtPrivate::qMetaTypeInterfaceForType<typename C::value_type>();
0442         else
0443             return nullptr;
0444     }
0445 
0446     static constexpr AddRemoveCapabilities getAddRemoveCapabilities()
0447     {
0448         AddRemoveCapabilities caps;
0449         if constexpr (QContainerInfo::has_push_back_v<C>)
0450             caps |= CanAddAtEnd;
0451         if constexpr (QContainerInfo::has_pop_back_v<C>)
0452             caps |= CanRemoveAtEnd;
0453         if constexpr (QContainerInfo::has_push_front_v<C>)
0454             caps |= CanAddAtBegin;
0455         if constexpr (QContainerInfo::has_pop_front_v<C>)
0456             caps |= CanRemoveAtBegin;
0457         return caps;
0458     }
0459 
0460     static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn()
0461     {
0462         if constexpr (QContainerInfo::has_at_index_v<C>) {
0463             return [](const void *c, qsizetype i, void *r) {
0464                 *static_cast<QContainerInfo::value_type<C> *>(r)
0465                         = static_cast<const C *>(c)->at(i);
0466             };
0467         } else if constexpr (QContainerInfo::can_get_at_index_v<C>) {
0468             return [](const void *c, qsizetype i, void *r) {
0469                 *static_cast<QContainerInfo::value_type<C> *>(r)
0470                         = (*static_cast<const C *>(c))[i];
0471             };
0472         } else {
0473             return nullptr;
0474         }
0475     }
0476 
0477     static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn()
0478     {
0479         if constexpr (QContainerInfo::can_set_at_index_v<C>) {
0480             return [](void *c, qsizetype i, const void *e) {
0481                 (*static_cast<C *>(c))[i]
0482                         = *static_cast<const QContainerInfo::value_type<C> *>(e);
0483             };
0484         } else {
0485             return nullptr;
0486         }
0487     }
0488 
0489     static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn()
0490     {
0491         if constexpr (QContainerInfo::has_push_back_v<C>) {
0492             if constexpr (QContainerInfo::has_push_front_v<C>) {
0493                 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
0494                     const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
0495                     switch (position) {
0496                     case QMetaSequenceInterface::AtBegin:
0497                         static_cast<C *>(c)->push_front(value);
0498                         break;
0499                     case QMetaSequenceInterface::AtEnd:
0500                     case QMetaSequenceInterface::Unspecified:
0501                         static_cast<C *>(c)->push_back(value);
0502                         break;
0503                     }
0504                 };
0505             } else {
0506                 return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
0507                     const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
0508                     switch (position) {
0509                     case QMetaSequenceInterface::AtBegin:
0510                         break;
0511                     case QMetaSequenceInterface::AtEnd:
0512                     case QMetaSequenceInterface::Unspecified:
0513                         static_cast<C *>(c)->push_back(value);
0514                         break;
0515                     }
0516                 };
0517             }
0518         } else if constexpr (QContainerInfo::has_push_front_v<C>) {
0519             return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
0520                 const auto &value = *static_cast<const QContainerInfo::value_type<C> *>(v);
0521                 switch (position) {
0522                 case QMetaSequenceInterface::Unspecified:
0523                 case QMetaSequenceInterface::AtBegin:
0524                     static_cast<C *>(c)->push_front(value);
0525                 case QMetaSequenceInterface::AtEnd:
0526                     break;
0527                 }
0528             };
0529         } else if constexpr (QContainerInfo::has_insert_v<C>) {
0530             return [](void *c, const void *v, QMetaSequenceInterface::Position position) {
0531                 if (position == QMetaSequenceInterface::Unspecified) {
0532                     static_cast<C *>(c)->insert(
0533                                 *static_cast<const QContainerInfo::value_type<C> *>(v));
0534                 }
0535             };
0536         } else {
0537             return nullptr;
0538         }
0539     }
0540 
0541     static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn()
0542     {
0543         if constexpr (QContainerInfo::has_pop_back_v<C>) {
0544             if constexpr (QContainerInfo::has_pop_front_v<C>) {
0545                 return [](void *c, QMetaSequenceInterface::Position position) {
0546                     switch (position) {
0547                     case QMetaSequenceInterface::AtBegin:
0548                         static_cast<C *>(c)->pop_front();
0549                         break;
0550                     case QMetaSequenceInterface::AtEnd:
0551                     case QMetaSequenceInterface::Unspecified:
0552                         static_cast<C *>(c)->pop_back();
0553                         break;
0554                     }
0555                 };
0556             } else {
0557                 return [](void *c, QMetaSequenceInterface::Position position) {
0558                     switch (position) {
0559                     case QMetaSequenceInterface::AtBegin:
0560                         break;
0561                     case QMetaSequenceInterface::Unspecified:
0562                     case QMetaSequenceInterface::AtEnd:
0563                         static_cast<C *>(c)->pop_back();
0564                         break;
0565                     }
0566                 };
0567             }
0568         } else if constexpr (QContainerInfo::has_pop_front_v<C>) {
0569             return [](void *c, QMetaSequenceInterface::Position position) {
0570                 switch (position) {
0571                 case QMetaSequenceInterface::Unspecified:
0572                 case QMetaSequenceInterface::AtBegin:
0573                     static_cast<C *>(c)->pop_front();
0574                     break;
0575                 case QMetaSequenceInterface::AtEnd:
0576                     break;
0577                 }
0578             };
0579         } else {
0580             return nullptr;
0581         }
0582     }
0583 
0584     static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn()
0585     {
0586         if constexpr (QContainerInfo::has_iterator_v<C>
0587                 && QContainerInfo::iterator_dereferences_to_value_v<C> && !std::is_const_v<C>) {
0588             return [](const void *i, void *r) {
0589                 *static_cast<QContainerInfo::value_type<C> *>(r) =
0590                         *(*static_cast<const QContainerInfo::iterator<C> *>(i));
0591             };
0592         } else {
0593             return nullptr;
0594         }
0595     }
0596 
0597     static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn()
0598     {
0599         if constexpr (QContainerInfo::has_iterator_v<C>
0600                 && QContainerInfo::can_set_value_at_iterator_v<C> && !std::is_const_v<C>) {
0601             return [](const void *i, const void *e) {
0602                 *(*static_cast<const QContainerInfo::iterator<C> *>(i))
0603                         = *static_cast<const QContainerInfo::value_type<C> *>(e);
0604             };
0605         } else {
0606             return nullptr;
0607         }
0608     }
0609 
0610     static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn()
0611     {
0612         if constexpr (QContainerInfo::has_iterator_v<C>
0613                 && QContainerInfo::can_insert_value_at_iterator_v<C> && !std::is_const_v<C>) {
0614             return [](void *c, const void *i, const void *e) {
0615                 static_cast<C *>(c)->insert(
0616                             *static_cast<const QContainerInfo::iterator<C> *>(i),
0617                             *static_cast<const QContainerInfo::value_type<C> *>(e));
0618             };
0619         } else {
0620             return nullptr;
0621         }
0622     }
0623 
0624     static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn()
0625     {
0626         if constexpr (QContainerInfo::has_const_iterator_v<C>
0627                 && QContainerInfo::iterator_dereferences_to_value_v<C>) {
0628             return [](const void *i, void *r) {
0629                 *static_cast<QContainerInfo::value_type<C> *>(r) =
0630                         *(*static_cast<const QContainerInfo::const_iterator<C> *>(i));
0631             };
0632         } else {
0633             return nullptr;
0634         }
0635     }
0636 
0637     static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn()
0638     {
0639         return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
0640                 QMetaSequenceInterface::EraseValueAtIteratorFn>();
0641     }
0642 
0643     static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn()
0644     {
0645         if constexpr (QContainerInfo::has_iterator_v<C>
0646                 && QContainerInfo::can_erase_range_at_iterator_v<C> && !std::is_const_v<C>) {
0647             return [](void *c, const void *i, const void *j) {
0648                 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::iterator<C> *>(i),
0649                                            *static_cast<const QContainerInfo::iterator<C> *>(j));
0650             };
0651         } else {
0652             return nullptr;
0653         }
0654     }
0655 };
0656 
0657 template<typename C>
0658 class QMetaAssociationForContainer : public QMetaContainerForContainer<C>
0659 {
0660     friend QMetaAssociationInterface;
0661 
0662     static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType()
0663     {
0664         if constexpr (QContainerInfo::has_key_type_v<C>)
0665             return QtPrivate::qMetaTypeInterfaceForType<typename C::key_type>();
0666         else
0667             return nullptr;
0668     }
0669 
0670     static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType()
0671     {
0672         if constexpr (QContainerInfo::has_mapped_type_v<C>)
0673             return QtPrivate::qMetaTypeInterfaceForType<typename C::mapped_type>();
0674         else
0675             return nullptr;
0676     }
0677 
0678     static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn()
0679     {
0680         if constexpr (QContainerInfo::can_insert_key_v<C>) {
0681             return [](void *c, const void *k) {
0682                 static_cast<C *>(c)->insert(
0683                             *static_cast<const QContainerInfo::key_type<C> *>(k));
0684             };
0685         } else if constexpr (QContainerInfo::can_insert_pair_v<C>) {
0686             return [](void *c, const void *k) {
0687                 static_cast<C *>(c)->insert(
0688                             {*static_cast<const QContainerInfo::key_type<C> *>(k), {}});
0689             };
0690         } else if constexpr (QContainerInfo::can_insert_key_mapped_v<C>) {
0691             return [](void *c, const void *k) {
0692                 static_cast<C *>(c)->insert(
0693                             *static_cast<const QContainerInfo::key_type<C> *>(k), {});
0694             };
0695         } else {
0696             return nullptr;
0697         }
0698     }
0699 
0700     static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn()
0701     {
0702         if constexpr (QContainerInfo::can_erase_at_key_v<C>) {
0703             return [](void *c, const void *k) {
0704                 static_cast<C *>(c)->erase(*static_cast<const QContainerInfo::key_type<C> *>(k));
0705             };
0706         } else if constexpr (QContainerInfo::can_remove_at_key_v<C>) {
0707             return [](void *c, const void *k) {
0708                 static_cast<C *>(c)->remove(*static_cast<const QContainerInfo::key_type<C> *>(k));
0709             };
0710         } else {
0711             return nullptr;
0712         }
0713     }
0714 
0715     static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn()
0716     {
0717         if constexpr (QContainerInfo::has_contains_v<C>) {
0718             return [](const void *c, const void *k) {
0719                 return static_cast<const C *>(c)->contains(
0720                             *static_cast<const QContainerInfo::key_type<C> *>(k));
0721             };
0722         } else if (QContainerInfo::has_find_v<C>) {
0723             return [](const void *c, const void *k) {
0724                 const C *container = static_cast<const C *>(c);
0725                 return container->find(
0726                             *static_cast<const QContainerInfo::key_type<C> *>(k))
0727                         != container->end();
0728             };
0729         } else {
0730             return nullptr;
0731         }
0732     }
0733 
0734     static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn()
0735     {
0736         if constexpr (QContainerInfo::has_at_key_v<C>) {
0737             return [](const void *c, const void *k, void *r) {
0738                 *static_cast<QContainerInfo::mapped_type<C> *>(r)
0739                         = static_cast<const C *>(c)->at(
0740                                 *static_cast<const QContainerInfo::key_type<C> *>(k));
0741             };
0742         } else if constexpr (QContainerInfo::can_get_at_key_v<C>) {
0743             return [](const void *c, const void *k, void *r) {
0744                 *static_cast<QContainerInfo::mapped_type<C> *>(r)
0745                         = (*static_cast<const C *>(c))[
0746                                 *static_cast<const QContainerInfo::key_type<C> *>(k)];
0747             };
0748         } else {
0749             return nullptr;
0750         }
0751     }
0752 
0753     static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn()
0754     {
0755         if constexpr (QContainerInfo::can_set_at_key_v<C>) {
0756             return [](void *c, const void *k, const void *m) {
0757                 (*static_cast<C *>(c))[*static_cast<const QContainerInfo::key_type<C> *>(k)] =
0758                         *static_cast<const QContainerInfo::mapped_type<C> *>(m);
0759             };
0760         } else {
0761             return nullptr;
0762         }
0763     }
0764 
0765     static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn()
0766     {
0767         if constexpr (QContainerInfo::has_find_v<C>) {
0768             return [](void *c, const void *k) -> void* {
0769                 using Iterator = QContainerInfo::iterator<C>;
0770                 return new Iterator(static_cast<C *>(c)->find(
0771                             *static_cast<const QContainerInfo::key_type<C> *>(k)));
0772             };
0773         } else {
0774             return nullptr;
0775         }
0776     }
0777 
0778     static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn()
0779     {
0780         if constexpr (QContainerInfo::has_find_v<C>) {
0781             return [](const void *c, const void *k) -> void* {
0782                 using Iterator = QContainerInfo::const_iterator<C>;
0783                 return new Iterator(static_cast<const C *>(c)->find(
0784                             *static_cast<const QContainerInfo::key_type<C> *>(k)));
0785             };
0786         } else {
0787             return nullptr;
0788         }
0789     }
0790 
0791     template<typename Iterator>
0792     static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn()
0793     {
0794         if constexpr (QContainerInfo::iterator_has_key_v<C>) {
0795             return [](const void *i, void *k) {
0796                 *static_cast<QContainerInfo::key_type<C> *>(k)
0797                         = static_cast<const Iterator *>(i)->key();
0798             };
0799         } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
0800                 && QContainerInfo::value_type_has_first_v<C>) {
0801             return [](const void *i, void *k) {
0802                 *static_cast<QContainerInfo::key_type<C> *>(k)
0803                         = (*static_cast<const Iterator *>(i))->first;
0804             };
0805         } else if constexpr (QContainerInfo::iterator_dereferences_to_key_v<C>) {
0806             return [](const void *i, void *k) {
0807                 *static_cast<QContainerInfo::key_type<C> *>(k)
0808                         = *(*static_cast<const Iterator *>(i));
0809             };
0810         } else {
0811             return nullptr;
0812         }
0813     }
0814 
0815     static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn()
0816     {
0817         return keyAtIteratorFn<QContainerInfo::iterator<C>>();
0818     }
0819 
0820     static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn()
0821     {
0822         return keyAtIteratorFn<QContainerInfo::const_iterator<C>>();
0823     }
0824 
0825     template<typename Iterator>
0826     static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn()
0827     {
0828         if constexpr (QContainerInfo::iterator_has_value_v<C>) {
0829             return [](const void *i, void *k) {
0830                 *static_cast<QContainerInfo::mapped_type<C> *>(k)
0831                         = static_cast<const Iterator *>(i)->value();
0832             };
0833         } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
0834                 && QContainerInfo::value_type_has_second_v<C>) {
0835             return [](const void *i, void *k) {
0836                 *static_cast<QContainerInfo::mapped_type<C> *>(k)
0837                         = (*static_cast<const Iterator *>(i))->second;
0838             };
0839         } else if constexpr (QContainerInfo::iterator_dereferences_to_mapped_v<C>) {
0840             return [](const void *i, void *k) {
0841                 *static_cast<QContainerInfo::mapped_type<C> *>(k)
0842                         = *static_cast<const Iterator *>(i);
0843             };
0844         } else {
0845             return nullptr;
0846         }
0847     }
0848 
0849     static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn()
0850     {
0851         return mappedAtIteratorFn<QContainerInfo::iterator<C>>();
0852     }
0853 
0854     static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn()
0855     {
0856         return mappedAtIteratorFn<QContainerInfo::const_iterator<C>>();
0857     }
0858 
0859     static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn()
0860     {
0861         if constexpr (QContainerInfo::can_set_mapped_at_iterator_v<C> && !std::is_const_v<C>) {
0862             return [](const void *i, const void *m) {
0863                 *(*static_cast<const QContainerInfo::iterator<C> *>(i))
0864                         = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
0865             };
0866         } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v<C>
0867                 && QContainerInfo::value_type_has_second_v<C>) {
0868             return [](const void *i, const void *m) {
0869                 (*static_cast<const QContainerInfo::iterator<C> *>(i))->second
0870                         = *static_cast<const QContainerInfo::mapped_type<C> *>(m);
0871             };
0872         } else {
0873             return nullptr;
0874         }
0875     }
0876 
0877     static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn()
0878     {
0879         return QMetaContainerForContainer<C>::template getEraseAtIteratorFn<
0880                 QMetaAssociationInterface::EraseKeyAtIteratorFn>();
0881     }
0882 };
0883 
0884 } // namespace QtMetaContainerPrivate
0885 
0886 class Q_CORE_EXPORT QMetaContainer
0887 {
0888 public:
0889     QMetaContainer() = default;
0890     explicit QMetaContainer(const QtMetaContainerPrivate::QMetaContainerInterface *d) : d_ptr(d) {}
0891 
0892     bool hasInputIterator() const;
0893     bool hasForwardIterator() const;
0894     bool hasBidirectionalIterator() const;
0895     bool hasRandomAccessIterator() const;
0896 
0897     bool hasSize() const;
0898     qsizetype size(const void *container) const;
0899 
0900     bool canClear() const;
0901     void clear(void *container) const;
0902 
0903     bool hasIterator() const;
0904     void *begin(void *container) const;
0905     void *end(void *container) const;
0906     void destroyIterator(const void *iterator) const;
0907     bool compareIterator(const void *i, const void *j) const;
0908     void copyIterator(void *target, const void *source) const;
0909     void advanceIterator(void *iterator, qsizetype step) const;
0910     qsizetype diffIterator(const void *i, const void *j) const;
0911 
0912     bool hasConstIterator() const;
0913     void *constBegin(const void *container) const;
0914     void *constEnd(const void *container) const;
0915     void destroyConstIterator(const void *iterator) const;
0916     bool compareConstIterator(const void *i, const void *j) const;
0917     void copyConstIterator(void *target, const void *source) const;
0918     void advanceConstIterator(void *iterator, qsizetype step) const;
0919     qsizetype diffConstIterator(const void *i, const void *j) const;
0920 
0921 protected:
0922     const QtMetaContainerPrivate::QMetaContainerInterface *d_ptr = nullptr;
0923 };
0924 
0925 class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
0926 {
0927 public:
0928     QMetaSequence() = default;
0929     explicit QMetaSequence(const QtMetaContainerPrivate::QMetaSequenceInterface *d) : QMetaContainer(d) {}
0930 
0931     template<typename T>
0932     static constexpr QMetaSequence fromContainer()
0933     {
0934         return QMetaSequence(&MetaSequence<T>::value);
0935     }
0936 
0937     QMetaType valueMetaType() const;
0938 
0939     bool isSortable() const;
0940     bool canAddValueAtBegin() const;
0941     void addValueAtBegin(void *container, const void *value) const;
0942     bool canAddValueAtEnd() const;
0943     void addValueAtEnd(void *container, const void *value) const;
0944     bool canRemoveValueAtBegin() const;
0945     void removeValueAtBegin(void *container) const;
0946     bool canRemoveValueAtEnd() const;
0947     void removeValueAtEnd(void *container) const;
0948 
0949     bool canGetValueAtIndex() const;
0950     void valueAtIndex(const void *container, qsizetype index, void *result) const;
0951 
0952     bool canSetValueAtIndex() const;
0953     void setValueAtIndex(void *container, qsizetype index, const void *value) const;
0954 
0955     bool canAddValue() const;
0956     void addValue(void *container, const void *value) const;
0957 
0958     bool canRemoveValue() const;
0959     void removeValue(void *container) const;
0960 
0961     bool canGetValueAtIterator() const;
0962     void valueAtIterator(const void *iterator, void *result) const;
0963 
0964     bool canSetValueAtIterator() const;
0965     void setValueAtIterator(const void *iterator, const void *value) const;
0966 
0967     bool canInsertValueAtIterator() const;
0968     void insertValueAtIterator(void *container, const void *iterator, const void *value) const;
0969 
0970     bool canEraseValueAtIterator() const;
0971     void eraseValueAtIterator(void *container, const void *iterator) const;
0972 
0973     bool canEraseRangeAtIterator() const;
0974     void eraseRangeAtIterator(void *container, const void *iterator1, const void *iterator2) const;
0975 
0976     bool canGetValueAtConstIterator() const;
0977     void valueAtConstIterator(const void *iterator, void *result) const;
0978 
0979     const QtMetaContainerPrivate::QMetaSequenceInterface *iface() const { return d(); }
0980 
0981 private:
0982     friend bool comparesEqual(const QMetaSequence &lhs, const QMetaSequence &rhs) noexcept
0983     {
0984         return lhs.d() == rhs.d();
0985     }
0986     Q_DECLARE_EQUALITY_COMPARABLE(QMetaSequence)
0987 
0988     template<typename T>
0989     struct MetaSequence
0990     {
0991         static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value
0992             = QtMetaContainerPrivate::QMetaSequenceInterface(
0993                     QtMetaContainerPrivate::QMetaSequenceForContainer<T>());
0994     };
0995 
0996     const QtMetaContainerPrivate::QMetaSequenceInterface *d() const
0997     {
0998         return static_cast<const QtMetaContainerPrivate::QMetaSequenceInterface *>(d_ptr);
0999     }
1000 };
1001 
1002 class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
1003 {
1004 public:
1005     QMetaAssociation() = default;
1006     explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {}
1007 
1008     template<typename T>
1009     static constexpr QMetaAssociation fromContainer()
1010     {
1011         return QMetaAssociation(&MetaAssociation<T>::value);
1012     }
1013 
1014     QMetaType keyMetaType() const;
1015     QMetaType mappedMetaType() const;
1016 
1017     bool canInsertKey() const
1018     {
1019         if (auto iface = d())
1020             return iface->insertKeyFn;
1021         return false;
1022     }
1023     void insertKey(void *container, const void *key) const
1024     {
1025         if (canInsertKey())
1026             d()->insertKeyFn(container, key);
1027     }
1028 
1029     bool canRemoveKey() const
1030     {
1031         if (auto iface = d())
1032             return iface->removeKeyFn;
1033         return false;
1034     }
1035     void removeKey(void *container, const void *key) const
1036     {
1037         if (canRemoveKey())
1038             d()->removeKeyFn(container, key);
1039     }
1040 
1041     bool canContainsKey() const
1042     {
1043         if (auto iface = d())
1044             return iface->containsKeyFn;
1045         return false;
1046     }
1047     bool containsKey(const void *container, const void *key) const
1048     {
1049         if (canContainsKey())
1050             return d()->containsKeyFn(container, key);
1051         return false;
1052     }
1053 
1054 
1055     bool canGetMappedAtKey() const
1056     {
1057         if (auto iface = d())
1058             return iface->mappedAtKeyFn;
1059         return false;
1060     }
1061     void mappedAtKey(const void *container, const void *key, void *mapped) const
1062     {
1063         if (canGetMappedAtKey())
1064             d()->mappedAtKeyFn(container, key, mapped);
1065     }
1066 
1067     bool canSetMappedAtKey() const
1068     {
1069         if (auto iface = d())
1070             return iface->setMappedAtKeyFn;
1071         return false;
1072     }
1073     void setMappedAtKey(void *container, const void *key, const void *mapped) const
1074     {
1075         if (canSetMappedAtKey())
1076             d()->setMappedAtKeyFn(container, key, mapped);
1077     }
1078 
1079     bool canGetKeyAtIterator() const
1080     {
1081         if (auto iface = d())
1082             return iface->keyAtIteratorFn;
1083         return false;
1084     }
1085 
1086     void keyAtIterator(const void *iterator, void *key) const
1087     {
1088         if (canGetKeyAtIterator())
1089             d()->keyAtIteratorFn(iterator, key);
1090     }
1091 
1092     bool canGetKeyAtConstIterator() const
1093     {
1094         if (auto iface = d())
1095             return iface->keyAtConstIteratorFn;
1096         return false;
1097     }
1098 
1099     void keyAtConstIterator(const void *iterator, void *key) const
1100     {
1101         if (canGetKeyAtConstIterator())
1102             d()->keyAtConstIteratorFn(iterator, key);
1103     }
1104 
1105     bool canGetMappedAtIterator() const
1106     {
1107         if (auto iface = d())
1108             return iface->mappedAtIteratorFn;
1109         return false;
1110     }
1111 
1112     void mappedAtIterator(const void *iterator, void *mapped) const
1113     {
1114         if (canGetMappedAtIterator())
1115             d()->mappedAtIteratorFn(iterator, mapped);
1116     }
1117 
1118     bool canGetMappedAtConstIterator() const
1119     {
1120         if (auto iface = d())
1121             return iface->mappedAtConstIteratorFn;
1122         return false;
1123     }
1124 
1125     void mappedAtConstIterator(const void *iterator, void *mapped) const
1126     {
1127         if (canGetMappedAtConstIterator())
1128             d()->mappedAtConstIteratorFn(iterator, mapped);
1129     }
1130 
1131     bool canSetMappedAtIterator() const
1132     {
1133         if (auto iface = d())
1134             return iface->setMappedAtIteratorFn;
1135         return false;
1136     }
1137 
1138     void setMappedAtIterator(const void *iterator, const void *mapped) const
1139     {
1140         if (canSetMappedAtIterator())
1141             d()->setMappedAtIteratorFn(iterator, mapped);
1142     }
1143 
1144     bool canCreateIteratorAtKey() const
1145     {
1146         if (auto iface = d())
1147             return iface->createIteratorAtKeyFn;
1148         return false;
1149     }
1150 
1151     void *createIteratorAtKey(void *container, const void *key) const
1152     {
1153         if (canCreateIteratorAtKey())
1154             return d()->createIteratorAtKeyFn(container, key);
1155         return nullptr;
1156     }
1157 
1158     bool canCreateConstIteratorAtKey() const
1159     {
1160         if (auto iface = d())
1161             return iface->createConstIteratorAtKeyFn;
1162         return false;
1163     }
1164 
1165     void *createConstIteratorAtKey(const void *container, const void *key) const
1166     {
1167         if (canCreateConstIteratorAtKey())
1168             return d()->createConstIteratorAtKeyFn(container, key);
1169         return nullptr;
1170     }
1171 
1172     const QtMetaContainerPrivate::QMetaAssociationInterface *iface() const { return d(); }
1173 
1174 private:
1175     friend bool comparesEqual(const QMetaAssociation &lhs, const QMetaAssociation &rhs) noexcept
1176     {
1177         return lhs.d() == rhs.d();
1178     }
1179     Q_DECLARE_EQUALITY_COMPARABLE(QMetaAssociation)
1180 
1181     template<typename T>
1182     struct MetaAssociation
1183     {
1184         static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value
1185                 = QtMetaContainerPrivate::QMetaAssociationInterface(
1186                         QtMetaContainerPrivate::QMetaAssociationForContainer<T>());
1187     };
1188 
1189     const QtMetaContainerPrivate::QMetaAssociationInterface *d() const
1190     {
1191         return static_cast<const QtMetaContainerPrivate::QMetaAssociationInterface *>(d_ptr);
1192     }
1193 };
1194 
1195 QT_END_NAMESPACE
1196 
1197 #endif // QMETACONTAINER_H