summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qmetacontainer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel/qmetacontainer.h')
-rw-r--r--src/corelib/kernel/qmetacontainer.h1197
1 files changed, 1197 insertions, 0 deletions
diff --git a/src/corelib/kernel/qmetacontainer.h b/src/corelib/kernel/qmetacontainer.h
new file mode 100644
index 0000000000..1bed7f9f7b
--- /dev/null
+++ b/src/corelib/kernel/qmetacontainer.h
@@ -0,0 +1,1197 @@
+// 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
+
+#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 {
+
+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;
+};
+
+class Q_CORE_EXPORT QMetaSequence : public QMetaContainer
+{
+public:
+ 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);
+ }
+};
+
+class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer
+{
+public:
+ 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