/**************************************************************************** ** ** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QMETACONTAINER_H #define QMETACONTAINER_H #include #include #include QT_BEGIN_NAMESPACE class QMetaType; namespace QtPrivate { class QMetaTypeInterface; template 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 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 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 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 class QMetaContainerForContainer { friend QMetaContainerInterface; template static constexpr IteratorCapabilities capabilitiesForIterator() { using Tag = typename std::iterator_traits::iterator_category; IteratorCapabilities caps {}; if constexpr (std::is_base_of_v) caps |= InputCapability; if constexpr (std::is_base_of_v) caps |= ForwardCapability; if constexpr (std::is_base_of_v) caps |= BiDirectionalCapability; if constexpr (std::is_base_of_v) caps |= RandomAccessCapability; return caps; } static constexpr IteratorCapabilities getIteratorCapabilities() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) return capabilitiesForIterator>(); else if constexpr (QContainerInfo::has_const_iterator_v) return capabilitiesForIterator>(); else return {}; } static constexpr QMetaContainerInterface::SizeFn getSizeFn() { if constexpr (QContainerInfo::has_size_v) { return [](const void *c) -> qsizetype { return static_cast(c)->size(); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::ClearFn getClearFn() { if constexpr (QContainerInfo::has_clear_v) { return [](void *c) { return static_cast(c)->clear(); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CreateIteratorFn getCreateIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](void *c, QMetaContainerInterface::Position p) -> void* { using Iterator = QContainerInfo::iterator; switch (p) { case QMetaContainerInterface::Unspecified: return new Iterator; case QMetaContainerInterface::AtBegin: return new Iterator(static_cast(c)->begin()); break; case QMetaContainerInterface::AtEnd: return new Iterator(static_cast(c)->end()); break; } return nullptr; }; } else { return nullptr; } } static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](const void *i) { using Iterator = QContainerInfo::iterator; delete static_cast(i); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CompareIteratorFn getCompareIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](const void *i, const void *j) { using Iterator = QContainerInfo::iterator; return *static_cast(i) == *static_cast(j); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CopyIteratorFn getCopyIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](void *i, const void *j) { using Iterator = QContainerInfo::iterator; *static_cast(i) = *static_cast(j); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](void *i, qsizetype step) { std::advance(*static_cast *>(i), step); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::DiffIteratorFn getDiffIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && !std::is_const_v) { return [](const void *i, const void *j) -> qsizetype { return std::distance(*static_cast *>(j), *static_cast *>(i)); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CreateConstIteratorFn getCreateConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](const void *c, QMetaContainerInterface::Position p) -> void* { using Iterator = QContainerInfo::const_iterator; switch (p) { case QMetaContainerInterface::Unspecified: return new Iterator; case QMetaContainerInterface::AtBegin: return new Iterator(static_cast(c)->begin()); case QMetaContainerInterface::AtEnd: return new Iterator(static_cast(c)->end()); } return nullptr; }; } else { return nullptr; } } static constexpr QMetaContainerInterface::DestroyIteratorFn getDestroyConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](const void *i) { using Iterator = QContainerInfo::const_iterator; delete static_cast(i); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CompareIteratorFn getCompareConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](const void *i, const void *j) { using Iterator = QContainerInfo::const_iterator; return *static_cast(i) == *static_cast(j); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::CopyIteratorFn getCopyConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](void *i, const void *j) { using Iterator = QContainerInfo::const_iterator; *static_cast(i) = *static_cast(j); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::AdvanceIteratorFn getAdvanceConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](void *i, qsizetype step) { std::advance(*static_cast *>(i), step); }; } else { return nullptr; } } static constexpr QMetaContainerInterface::DiffIteratorFn getDiffConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v) { return [](const void *i, const void *j) -> qsizetype { return std::distance(*static_cast *>(j), *static_cast *>(i)); }; } else { return nullptr; } } protected: template static constexpr EraseFn getEraseAtIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && QContainerInfo::can_erase_at_iterator_v && !std::is_const_v) { return [](void *c, const void *i) { static_cast(c)->erase(*static_cast *>(i)); }; } else { return nullptr; } } }; template class QMetaSequenceForContainer : public QMetaContainerForContainer { friend QMetaSequenceInterface; static constexpr const QtPrivate::QMetaTypeInterface *getValueMetaType() { if constexpr (QContainerInfo::has_value_type_v) return QtPrivate::qMetaTypeInterfaceForType(); else return nullptr; } static constexpr AddRemoveCapabilities getAddRemoveCapabilities() { AddRemoveCapabilities caps; if constexpr (QContainerInfo::has_push_back_v) caps |= CanAddAtEnd; if constexpr (QContainerInfo::has_pop_back_v) caps |= CanRemoveAtEnd; if constexpr (QContainerInfo::has_push_front_v) caps |= CanAddAtBegin; if constexpr (QContainerInfo::has_pop_front_v) caps |= CanRemoveAtBegin; return caps; } static constexpr QMetaSequenceInterface::ValueAtIndexFn getValueAtIndexFn() { if constexpr (QContainerInfo::has_at_index_v) { return [](const void *c, qsizetype i, void *r) { *static_cast *>(r) = static_cast(c)->at(i); }; } else if constexpr (QContainerInfo::can_get_at_index_v) { return [](const void *c, qsizetype i, void *r) { *static_cast *>(r) = (*static_cast(c))[i]; }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::SetValueAtIndexFn getSetValueAtIndexFn() { if constexpr (QContainerInfo::can_set_at_index_v) { return [](void *c, qsizetype i, const void *e) { (*static_cast(c))[i] = *static_cast *>(e); }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::AddValueFn getAddValueFn() { if constexpr (QContainerInfo::has_push_back_v) { if constexpr (QContainerInfo::has_push_front_v) { return [](void *c, const void *v, QMetaSequenceInterface::Position position) { const auto &value = *static_cast *>(v); switch (position) { case QMetaSequenceInterface::AtBegin: static_cast(c)->push_front(value); break; case QMetaSequenceInterface::AtEnd: case QMetaSequenceInterface::Unspecified: static_cast(c)->push_back(value); break; } }; } else { return [](void *c, const void *v, QMetaSequenceInterface::Position position) { const auto &value = *static_cast *>(v); switch (position) { case QMetaSequenceInterface::AtBegin: break; case QMetaSequenceInterface::AtEnd: case QMetaSequenceInterface::Unspecified: static_cast(c)->push_back(value); break; } }; } } else if constexpr (QContainerInfo::has_push_front_v) { return [](void *c, const void *v, QMetaSequenceInterface::Position position) { const auto &value = *static_cast *>(v); switch (position) { case QMetaSequenceInterface::Unspecified: case QMetaSequenceInterface::AtBegin: static_cast(c)->push_front(value); case QMetaSequenceInterface::AtEnd: break; } }; } else if constexpr (QContainerInfo::has_insert_v) { return [](void *c, const void *v, QMetaSequenceInterface::Position position) { if (position == QMetaSequenceInterface::Unspecified) { static_cast(c)->insert( *static_cast *>(v)); } }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::RemoveValueFn getRemoveValueFn() { if constexpr (QContainerInfo::has_pop_back_v) { if constexpr (QContainerInfo::has_pop_front_v) { return [](void *c, QMetaSequenceInterface::Position position) { switch (position) { case QMetaSequenceInterface::AtBegin: static_cast(c)->pop_front(); break; case QMetaSequenceInterface::AtEnd: case QMetaSequenceInterface::Unspecified: static_cast(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)->pop_back(); break; } }; } } else if constexpr (QContainerInfo::has_pop_front_v) { return [](void *c, QMetaSequenceInterface::Position position) { switch (position) { case QMetaSequenceInterface::Unspecified: case QMetaSequenceInterface::AtBegin: static_cast(c)->pop_front(); break; case QMetaSequenceInterface::AtEnd: break; } }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && QContainerInfo::iterator_dereferences_to_value_v && !std::is_const_v) { return [](const void *i, void *r) { *static_cast *>(r) = *(*static_cast *>(i)); }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::SetValueAtIteratorFn getSetValueAtIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && QContainerInfo::can_set_value_at_iterator_v && !std::is_const_v) { return [](const void *i, const void *e) { *(*static_cast *>(i)) = *static_cast *>(e); }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::InsertValueAtIteratorFn getInsertValueAtIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && QContainerInfo::can_insert_value_at_iterator_v && !std::is_const_v) { return [](void *c, const void *i, const void *e) { static_cast(c)->insert( *static_cast *>(i), *static_cast *>(e)); }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::ValueAtIteratorFn getValueAtConstIteratorFn() { if constexpr (QContainerInfo::has_const_iterator_v && QContainerInfo::iterator_dereferences_to_value_v) { return [](const void *i, void *r) { *static_cast *>(r) = *(*static_cast *>(i)); }; } else { return nullptr; } } static constexpr QMetaSequenceInterface::EraseValueAtIteratorFn getEraseValueAtIteratorFn() { return QMetaContainerForContainer::template getEraseAtIteratorFn< QMetaSequenceInterface::EraseValueAtIteratorFn>(); } static constexpr QMetaSequenceInterface::EraseRangeAtIteratorFn getEraseRangeAtIteratorFn() { if constexpr (QContainerInfo::has_iterator_v && QContainerInfo::can_erase_range_at_iterator_v && !std::is_const_v) { return [](void *c, const void *i, const void *j) { static_cast(c)->erase(*static_cast *>(i), *static_cast *>(j)); }; } else { return nullptr; } } }; template class QMetaAssociationForContainer : public QMetaContainerForContainer { friend QMetaAssociationInterface; static constexpr const QtPrivate::QMetaTypeInterface *getKeyMetaType() { if constexpr (QContainerInfo::has_key_type_v) return QtPrivate::qMetaTypeInterfaceForType(); else return nullptr; } static constexpr const QtPrivate::QMetaTypeInterface *getMappedMetaType() { if constexpr (QContainerInfo::has_mapped_type_v) return QtPrivate::qMetaTypeInterfaceForType(); else return nullptr; } static constexpr QMetaAssociationInterface::InsertKeyFn getInsertKeyFn() { if constexpr (QContainerInfo::can_insert_key_v) { return [](void *c, const void *k) { static_cast(c)->insert( *static_cast *>(k)); }; } else if constexpr (QContainerInfo::can_insert_pair_v) { return [](void *c, const void *k) { static_cast(c)->insert( {*static_cast *>(k), {}}); }; } else if constexpr (QContainerInfo::can_insert_key_mapped_v) { return [](void *c, const void *k) { static_cast(c)->insert( *static_cast *>(k), {}); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::RemoveKeyFn getRemoveKeyFn() { if constexpr (QContainerInfo::can_erase_at_key_v) { return [](void *c, const void *k) { static_cast(c)->erase(*static_cast *>(k)); }; } else if constexpr (QContainerInfo::can_remove_at_key_v) { return [](void *c, const void *k) { static_cast(c)->remove(*static_cast *>(k)); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::ContainsKeyFn getContainsKeyFn() { if constexpr (QContainerInfo::has_contains_v) { return [](const void *c, const void *k) { return static_cast(c)->contains( *static_cast *>(k)); }; } else if (QContainerInfo::has_find_v) { return [](const void *c, const void *k) { const C *container = static_cast(c); return container->find( *static_cast *>(k)) != container->end(); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::MappedAtKeyFn getMappedAtKeyFn() { if constexpr (QContainerInfo::has_at_key_v) { return [](const void *c, const void *k, void *r) { *static_cast *>(r) = static_cast(c)->at( *static_cast *>(k)); }; } else if constexpr (QContainerInfo::can_get_at_key_v) { return [](const void *c, const void *k, void *r) { *static_cast *>(r) = (*static_cast(c))[ *static_cast *>(k)]; }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::SetMappedAtKeyFn getSetMappedAtKeyFn() { if constexpr (QContainerInfo::can_set_at_key_v) { return [](void *c, const void *k, const void *m) { (*static_cast(c))[*static_cast *>(k)] = *static_cast *>(m); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::CreateIteratorAtKeyFn createIteratorAtKeyFn() { if constexpr (QContainerInfo::has_find_v) { return [](void *c, const void *k) -> void* { using Iterator = QContainerInfo::iterator; return new Iterator(static_cast(c)->find( *static_cast *>(k))); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::CreateConstIteratorAtKeyFn createConstIteratorAtKeyFn() { if constexpr (QContainerInfo::has_find_v) { return [](const void *c, const void *k) -> void* { using Iterator = QContainerInfo::const_iterator; return new Iterator(static_cast(c)->find( *static_cast *>(k))); }; } else { return nullptr; } } template static constexpr QMetaAssociationInterface::KeyAtIteratorFn keyAtIteratorFn() { if constexpr (QContainerInfo::iterator_has_key_v) { return [](const void *i, void *k) { *static_cast *>(k) = static_cast(i)->key(); }; } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v && QContainerInfo::value_type_has_first_v) { return [](const void *i, void *k) { *static_cast *>(k) = (*static_cast(i))->first; }; } else if constexpr (QContainerInfo::iterator_dereferences_to_key_v) { return [](const void *i, void *k) { *static_cast *>(k) = *(*static_cast(i)); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtIteratorFn() { return keyAtIteratorFn>(); } static constexpr QMetaAssociationInterface::KeyAtIteratorFn getKeyAtConstIteratorFn() { return keyAtIteratorFn>(); } template static constexpr QMetaAssociationInterface::MappedAtIteratorFn mappedAtIteratorFn() { if constexpr (QContainerInfo::iterator_has_value_v) { return [](const void *i, void *k) { *static_cast *>(k) = static_cast(i)->value(); }; } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v && QContainerInfo::value_type_has_second_v) { return [](const void *i, void *k) { *static_cast *>(k) = (*static_cast(i))->second; }; } else if constexpr (QContainerInfo::iterator_dereferences_to_mapped_v) { return [](const void *i, void *k) { *static_cast *>(k) = *static_cast(i); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtIteratorFn() { return mappedAtIteratorFn>(); } static constexpr QMetaAssociationInterface::MappedAtIteratorFn getMappedAtConstIteratorFn() { return mappedAtIteratorFn>(); } static constexpr QMetaAssociationInterface::SetMappedAtIteratorFn getSetMappedAtIteratorFn() { if constexpr (QContainerInfo::can_set_mapped_at_iterator_v && !std::is_const_v) { return [](const void *i, const void *m) { *(*static_cast *>(i)) = *static_cast *>(m); }; } else if constexpr (QContainerInfo::iterator_dereferences_to_value_v && QContainerInfo::value_type_has_second_v) { return [](const void *i, const void *m) { (*static_cast *>(i))->second = *static_cast *>(m); }; } else { return nullptr; } } static constexpr QMetaAssociationInterface::EraseKeyAtIteratorFn getEraseKeyAtIteratorFn() { return QMetaContainerForContainer::template getEraseAtIteratorFn< QMetaAssociationInterface::EraseKeyAtIteratorFn>(); } }; } // 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 static constexpr QMetaSequence fromContainer() { return QMetaSequence(&MetaSequence::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; friend bool operator==(const QMetaSequence &a, const QMetaSequence &b) { return a.d() == b.d(); } friend bool operator!=(const QMetaSequence &a, const QMetaSequence &b) { return a.d() != b.d(); } private: template struct MetaSequence { static constexpr const QtMetaContainerPrivate::QMetaSequenceInterface value = QtMetaContainerPrivate::QMetaSequenceInterface( QtMetaContainerPrivate::QMetaSequenceForContainer()); }; const QtMetaContainerPrivate::QMetaSequenceInterface *d() const { return static_cast(d_ptr); } }; class Q_CORE_EXPORT QMetaAssociation : public QMetaContainer { public: QMetaAssociation() = default; explicit QMetaAssociation(const QtMetaContainerPrivate::QMetaAssociationInterface *d) : QMetaContainer(d) {} template static constexpr QMetaAssociation fromContainer() { return QMetaAssociation(&MetaAssociation::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; } friend bool operator==(const QMetaAssociation &a, const QMetaAssociation &b) { return a.d() == b.d(); } friend bool operator!=(const QMetaAssociation &a, const QMetaAssociation &b) { return a.d() != b.d(); } private: template struct MetaAssociation { static constexpr const QtMetaContainerPrivate::QMetaAssociationInterface value = QtMetaContainerPrivate::QMetaAssociationInterface( QtMetaContainerPrivate::QMetaAssociationForContainer()); }; const QtMetaContainerPrivate::QMetaAssociationInterface *d() const { return static_cast(d_ptr); } }; QT_END_NAMESPACE #endif // QMETACONTAINER_H