diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 0b8be3af89..4ccfc7b7f0 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -892,6 +892,7 @@ public: typedef VariantData (*getFunc)( void * const *p, int metaTypeId, uint flags); typedef void (*destroyIterFunc)(void **p); typedef bool (*equalIterFunc)(void * const *p, void * const *other); + typedef void (*copyIterFunc)(void **, void * const *); sizeFunc _size; atFunc _at; @@ -901,6 +902,7 @@ public: getFunc _get; destroyIterFunc _destroyIter; equalIterFunc _equalIter; + copyIterFunc _copyIter; template static int sizeImpl(const void *p) @@ -938,6 +940,10 @@ public: static VariantData getImpl(void * const *iterator, int metaTypeId, uint flags) { return VariantData(metaTypeId, IteratorOwner::getData(iterator), flags); } + template + static void copyIterImpl(void **dest, void * const * src) + { IteratorOwner::assign(dest, *static_cast(*src)); } + public: template QSequentialIterableImpl(const T*p) : _iterable(p) @@ -953,6 +959,7 @@ public: , _get(getImpl) , _destroyIter(destroyIterImpl) , _equalIter(equalIterImpl) + , _copyIter(copyIterImpl) { } @@ -970,6 +977,7 @@ public: , _get(0) , _destroyIter(0) , _equalIter(0) + , _copyIter(0) { } @@ -990,6 +998,12 @@ public: int size() const { Q_ASSERT(_iterable); return _size(_iterable); } inline void destroyIter() { _destroyIter(&_iterator); } + + void copy(const QSequentialIterableImpl &other) + { + *this = other; + _copyIter(&_iterator, &other._iterator); + } }; template @@ -1055,6 +1069,7 @@ public: typedef VariantData (*getFunc)(void * const *p, int metaTypeId, uint flags); typedef void (*destroyIterFunc)(void **p); typedef bool (*equalIterFunc)(void * const *p, void * const *other); + typedef void (*copyIterFunc)(void **, void * const *); sizeFunc _size; findFunc _find; @@ -1065,6 +1080,7 @@ public: getFunc _getValue; destroyIterFunc _destroyIter; equalIterFunc _equalIter; + copyIterFunc _copyIter; template static int sizeImpl(const void *p) @@ -1104,6 +1120,10 @@ public: static bool equalIterImpl(void * const *iterator, void * const *other) { return *static_cast(*iterator) == *static_cast(*other); } + template + static void copyIterImpl(void **dest, void * const * src) + { IteratorOwner::assign(dest, *static_cast(*src)); } + public: template QAssociativeIterableImpl(const T*p) : _iterable(p) @@ -1120,6 +1140,7 @@ public: , _getValue(getValueImpl) , _destroyIter(destroyIterImpl) , _equalIter(equalIterImpl) + , _copyIter(copyIterImpl) { } @@ -1138,6 +1159,7 @@ public: , _getValue(0) , _destroyIter(0) , _equalIter(0) + , _copyIter(0) { } @@ -1155,6 +1177,12 @@ public: { _find(_iterable, key.data, &_iterator); } int size() const { Q_ASSERT(_iterable); return _size(_iterable); } + + void copy(const QAssociativeIterableImpl &other) + { + *this = other; + _copyIter(&_iterator, &other._iterator); + } }; template diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 3345131c0f..3115c6a50b 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -615,8 +615,8 @@ public: inline const_iterator operator--(int) { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); } inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; } inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; } - inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); } - inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); } + inline const_iterator operator+(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl; impl.copy(m_impl); impl.advance(j); return const_iterator(impl, new QAtomicInt(0)); } + inline const_iterator operator-(int j) const { QtMetaTypePrivate::QSequentialIterableImpl impl; impl.copy(m_impl); impl.advance(-j); return const_iterator(impl, new QAtomicInt(0)); } }; friend struct const_iterator; @@ -700,8 +700,8 @@ public: inline const_iterator operator--(int) { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; m_impl.advance(-1); return const_iterator(impl, this->ref); } inline const_iterator &operator+=(int j) { m_impl.advance(j); return *this; } inline const_iterator &operator-=(int j) { m_impl.advance(-j); return *this; } - inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(j); return const_iterator(impl, this->ref); } - inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl = m_impl; impl.advance(-j); return const_iterator(impl, this->ref); } + inline const_iterator operator+(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl; impl.copy(m_impl); impl.advance(j); return const_iterator(impl, new QAtomicInt(0)); } + inline const_iterator operator-(int j) const { QtMetaTypePrivate::QAssociativeIterableImpl impl; impl.copy(m_impl); impl.advance(-j); return const_iterator(impl, new QAtomicInt(0)); } }; friend struct const_iterator; diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index c59e87cf13..52319f47fd 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -3818,6 +3818,20 @@ void tst_QVariant::iterateContainerElements() TEST_SEQUENTIAL_ITERATION(std::forward_list, QString) #endif + { + QVariantList ints; + ints << 1 << 2 << 3; + QVariant var = QVariant::fromValue(ints); + QSequentialIterable iter = var.value(); + QSequentialIterable::const_iterator it = iter.begin(); + QSequentialIterable::const_iterator end = iter.end(); + QCOMPARE(ints.at(1), *(it + 1)); + int i = 0; + for ( ; it != end; ++it, ++i) { + QCOMPARE(ints.at(i), *it); + } + } + #define TEST_ASSOCIATIVE_ITERATION(CONTAINER, KEY_TYPE, MAPPED_TYPE) \ { \ int numSeen = 0; \ @@ -3852,6 +3866,22 @@ void tst_QVariant::iterateContainerElements() #ifdef TEST_UNORDERED_MAP TEST_ASSOCIATIVE_ITERATION(std::unordered_map, int, bool) #endif + + { + QMap mapping; + mapping.insert(1, "one"); + mapping.insert(2, "two"); + mapping.insert(3, "three"); + QVariant var = QVariant::fromValue(mapping); + QAssociativeIterable iter = var.value(); + QAssociativeIterable::const_iterator it = iter.begin(); + QAssociativeIterable::const_iterator end = iter.end(); + QCOMPARE(*(mapping.begin() + 1), (*(it + 1)).toString()); + int i = 0; + for ( ; it != end; ++it, ++i) { + QCOMPARE(*(mapping.begin() + i), (*it).toString()); + } + } } void tst_QVariant::pairElements()