forked from qt-creator/qt-creator
Utils::transform: Add support for various map types as result
Add support for output as std::map/unordered_map/set and QMap and QHash, when giving the full result type as template argument. For std:: (unordered_)map, the function must return a std::pair<Key,Value>, for QMap and QHash it can also be QPair<Key,Value>. Change-Id: If3dff17ab6aa5d1b11abc244813fd885d10c75a4 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -30,9 +30,12 @@
|
||||
#include <qcompilerdetection.h> // for Q_REQUIRED_RESULT
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
@@ -310,6 +313,30 @@ public:
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
// for QMap / QHash, inserting a std::pair / QPair
|
||||
template <class Container>
|
||||
class MapInsertIterator :
|
||||
public std::iterator<std::output_iterator_tag,void,void,void,void>
|
||||
{
|
||||
protected:
|
||||
Container *container;
|
||||
|
||||
public:
|
||||
typedef Container container_type;
|
||||
explicit MapInsertIterator (Container &x)
|
||||
: container(&x) {}
|
||||
MapInsertIterator<Container> &operator=(const std::pair<const typename Container::key_type, typename Container::mapped_type> &value)
|
||||
{ container->insert(value.first, value.second); return *this; }
|
||||
MapInsertIterator<Container> &operator=(const QPair<typename Container::key_type, typename Container::mapped_type> &value)
|
||||
{ container->insert(value.first, value.second); return *this; }
|
||||
MapInsertIterator<Container >&operator*()
|
||||
{ return *this; }
|
||||
MapInsertIterator<Container> &operator++()
|
||||
{ return *this; }
|
||||
MapInsertIterator<Container> operator++(int)
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
// inserter helper function, returns a std::back_inserter for most containers
|
||||
// and is overloaded for QSet<> and other containers without push_back, returning custom inserters
|
||||
template<typename C>
|
||||
@@ -333,6 +360,41 @@ inserter(std::set<K, C, A> &container)
|
||||
return SetInsertIterator<std::set<K, C, A>>(container);
|
||||
}
|
||||
|
||||
template<typename K, typename H, typename C, typename A>
|
||||
inline SetInsertIterator<std::unordered_set<K, H, C, A>>
|
||||
inserter(std::unordered_set<K, H, C, A> &container)
|
||||
{
|
||||
return SetInsertIterator<std::unordered_set<K, H, C, A>>(container);
|
||||
}
|
||||
|
||||
template<typename K, typename V, typename C, typename A>
|
||||
inline SetInsertIterator<std::map<K, V, C, A>>
|
||||
inserter(std::map<K, V, C, A> &container)
|
||||
{
|
||||
return SetInsertIterator<std::map<K, V, C, A>>(container);
|
||||
}
|
||||
|
||||
template<typename K, typename V, typename H, typename C, typename A>
|
||||
inline SetInsertIterator<std::unordered_map<K, V, H, C, A>>
|
||||
inserter(std::unordered_map<K, V, H, C, A> &container)
|
||||
{
|
||||
return SetInsertIterator<std::unordered_map<K, V, H, C, A>>(container);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
inline MapInsertIterator<QMap<K, V>>
|
||||
inserter(QMap<K, V> &container)
|
||||
{
|
||||
return MapInsertIterator<QMap<K, V>>(container);
|
||||
}
|
||||
|
||||
template<typename K, typename V>
|
||||
inline MapInsertIterator<QHash<K, V>>
|
||||
inserter(QHash<K, V> &container)
|
||||
{
|
||||
return MapInsertIterator<QHash<K, V>>(container);
|
||||
}
|
||||
|
||||
// Helper code for container.reserve that makes it possible to effectively disable it for
|
||||
// specific cases
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <valarray>
|
||||
|
||||
// must get included after the containers above or gcc4.9 will have a problem using
|
||||
@@ -359,6 +360,70 @@ void tst_Algorithm::transform()
|
||||
const std::set<int> trans = Utils::transform<std::set<int>>(v, [](int i) { return i + 1; });
|
||||
QCOMPARE(trans, std::set<int>({2, 3, 4, 5}));
|
||||
}
|
||||
// various map/set/hash without push_back
|
||||
{
|
||||
// std::vector -> std::map
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const std::map<int, int> trans = Utils::transform<std::map<int, int>>(v, [](int i) {
|
||||
return std::make_pair(i, i + 1);
|
||||
});
|
||||
const std::map<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
{
|
||||
// std::vector -> std::unordered_set
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const std::unordered_set<int> trans = Utils::transform<std::unordered_set<int>>(v, [](int i) {
|
||||
return i + 1;
|
||||
});
|
||||
QCOMPARE(trans, std::unordered_set<int>({2, 3, 4, 5}));
|
||||
}
|
||||
{
|
||||
// std::vector -> std::unordered_map
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const std::unordered_map<int, int> trans
|
||||
= Utils::transform<std::unordered_map<int, int>>(v, [](int i) {
|
||||
return std::make_pair(i, i + 1);
|
||||
});
|
||||
const std::unordered_map<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
{
|
||||
// std::vector -> QMap using std::pair
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const QMap<int, int> trans = Utils::transform<QMap<int, int>>(v, [](int i) {
|
||||
return std::make_pair(i, i + 1);
|
||||
});
|
||||
const QMap<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
{
|
||||
// std::vector -> QMap using QPair
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const QMap<int, int> trans = Utils::transform<QMap<int, int>>(v, [](int i) {
|
||||
return qMakePair(i, i + 1);
|
||||
});
|
||||
const QMap<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
{
|
||||
// std::vector -> QHash using std::pair
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const QHash<int, int> trans = Utils::transform<QHash<int, int>>(v, [](int i) {
|
||||
return std::make_pair(i, i + 1);
|
||||
});
|
||||
const QHash<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
{
|
||||
// std::vector -> QHash using QPair
|
||||
const std::vector<int> v({1, 2, 3, 4});
|
||||
const QHash<int, int> trans = Utils::transform<QHash<int, int>>(v, [](int i) {
|
||||
return qMakePair(i, i + 1);
|
||||
});
|
||||
const QHash<int, int> expected({{1, 2}, {2, 3}, {3, 4}, {4, 5}});
|
||||
QCOMPARE(trans, expected);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_Algorithm::sort()
|
||||
|
||||
Reference in New Issue
Block a user