summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qiterator.h
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-03-01 04:24:38 +0100
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-03-04 00:21:44 +0100
commit0deff80eabd577f3514d255e32f74502c914dfe1 (patch)
tree353014233bbb87123679ac985de18daee3834341 /src/corelib/tools/qiterator.h
parentdd5fc20e902187356538d1c993d9ece729f6f505 (diff)
Associative containers: add a way to obtain a key/value range
Our associative containers' iterator's value_type isn't a destructurable type (yielding key/value). This means that something like for (auto [k, v] : map) doesn't even compile -- one can only "directly" iterate on the values. For quite some time we've had QKeyValueIterator to allow key/value iteration, but then one had to resort to a "traditional" for loop: for (auto i = map.keyValueBegin(), e = keyValueEnd(); i!=e; ++i) This can be easily packaged in an adaptor class, which is what this commmit does, thereby offering a C++17-compatible way to obtain key/value iteration over associative containers. Something possibly peculiar is the fact that the range so obtained is a range of pairs of references -- not a range of references to pairs. But that's easily explained by the fact that we have no pairs to build references to; hence, for (auto &[k, v] : map.asKeyValueRange()) doesn't compile (lvalue reference doesn't bind to prvalue pair). Instead, both of these compile: for (auto [k, v] : map.asKeyValueRange()) for (auto &&[k, v] : map.asKeyValueRange()) and in *both* cases one gets references to the keys/values in the map. If the map is non-const, the reference to the value is mutable. Last but not least, implement pinning for rvalue containers. [ChangeLog][QtCore][QMap] Added asKeyValueRange(). [ChangeLog][QtCore][QMultiMap] Added asKeyValueRange(). [ChangeLog][QtCore][QHash] Added asKeyValueRange(). [ChangeLog][QtCore][QMultiHash] Added asKeyValueRange(). Task-number: QTBUG-4615 Change-Id: Ic8506bff38b2f753494b21ab76f52e05c06ffc8b Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/tools/qiterator.h')
-rw-r--r--src/corelib/tools/qiterator.h41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 8922f34758..559023d493 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -301,6 +301,47 @@ private:
Iterator i;
};
+namespace QtPrivate {
+
+template <typename Map>
+class QKeyValueRangeStorage
+{
+protected:
+ Map m_map;
+public:
+ explicit QKeyValueRangeStorage(const Map &map) : m_map(map) {}
+ explicit QKeyValueRangeStorage(Map &&map) : m_map(std::move(map)) {}
+};
+
+template <typename Map>
+class QKeyValueRangeStorage<Map &>
+{
+protected:
+ Map &m_map;
+public:
+ explicit QKeyValueRangeStorage(Map &map) : m_map(map) {}
+};
+
+template <typename Map>
+class QKeyValueRange : public QKeyValueRangeStorage<Map>
+{
+public:
+ using QKeyValueRangeStorage<Map>::QKeyValueRangeStorage;
+ auto begin() { return this->m_map.keyValueBegin(); }
+ auto begin() const { return this->m_map.keyValueBegin(); }
+ auto end() { return this->m_map.keyValueEnd(); }
+ auto end() const { return this->m_map.keyValueEnd(); }
+};
+
+template <typename Map>
+QKeyValueRange(Map &) -> QKeyValueRange<Map &>;
+
+template <typename Map, std::enable_if_t<!std::is_reference_v<Map>, bool> = false>
+QKeyValueRange(Map &&) -> QKeyValueRange<std::remove_const_t<Map>>;
+
+} // namespace QtPrivate
+
+
QT_END_NAMESPACE
#endif // QITERATOR_H