aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libs/utils/algorithm.h48
-rw-r--r--tests/auto/algorithm/tst_algorithm.cpp36
2 files changed, 70 insertions, 14 deletions
diff --git a/src/libs/utils/algorithm.h b/src/libs/utils/algorithm.h
index 64fe9f58c10..6e4543e2a50 100644
--- a/src/libs/utils/algorithm.h
+++ b/src/libs/utils/algorithm.h
@@ -31,6 +31,7 @@
#include <algorithm>
#include <memory>
+#include <set>
#include <tuple>
#include <QObject>
@@ -284,10 +285,10 @@ namespace {
// and insert for QSet<>
//
-// QSetInsertIterator, straight from the standard for insert_iterator
+// SetInsertIterator, straight from the standard for insert_iterator
// just without the additional parameter to insert
template <class Container>
- class QSetInsertIterator :
+ class SetInsertIterator :
public std::iterator<std::output_iterator_tag,void,void,void,void>
{
protected:
@@ -295,22 +296,22 @@ protected:
public:
typedef Container container_type;
- explicit QSetInsertIterator (Container &x)
+ explicit SetInsertIterator (Container &x)
: container(&x) {}
- QSetInsertIterator<Container> &operator=(const typename Container::value_type &value)
+ SetInsertIterator<Container> &operator=(const typename Container::value_type &value)
{ container->insert(value); return *this; }
- QSetInsertIterator<Container> &operator= (typename Container::value_type &&value)
+ SetInsertIterator<Container> &operator= (typename Container::value_type &&value)
{ container->insert(std::move(value)); return *this; }
- QSetInsertIterator<Container >&operator*()
+ SetInsertIterator<Container >&operator*()
{ return *this; }
- QSetInsertIterator<Container> &operator++()
+ SetInsertIterator<Container> &operator++()
{ return *this; }
- QSetInsertIterator<Container> operator++(int)
+ SetInsertIterator<Container> operator++(int)
{ return *this; }
};
// inserter helper function, returns a std::back_inserter for most containers
-// and is overloaded for QSet<> to return a QSetInsertIterator
+// and is overloaded for QSet<> and other containers without push_back, returning custom inserters
template<typename C>
inline std::back_insert_iterator<C>
inserter(C &container)
@@ -319,12 +320,35 @@ inserter(C &container)
}
template<typename X>
-inline QSetInsertIterator<QSet<X>>
+inline SetInsertIterator<QSet<X>>
inserter(QSet<X> &container)
{
- return QSetInsertIterator<QSet<X>>(container);
+ return SetInsertIterator<QSet<X>>(container);
}
+template<typename K, typename C, typename A>
+inline SetInsertIterator<std::set<K, C, A>>
+inserter(std::set<K, C, A> &container)
+{
+ return SetInsertIterator<std::set<K, C, A>>(container);
+}
+
+// Helper code for container.reserve that makes it possible to effectively disable it for
+// specific cases
+
+// default: do reserve
+// Template arguments are more specific than the second version below, so this is tried first
+template<template<typename...> class C, typename... CArgs,
+ typename = decltype(&C<CArgs...>::reserve)>
+void reserve(C<CArgs...> &c, typename C<CArgs...>::size_type s)
+{
+ c.reserve(s);
+}
+
+// containers that don't have reserve()
+template<typename C>
+void reserve(C &, typename C::size_type) { }
+
} // anonymous
// --------------------------------------------------------------------
@@ -341,7 +365,7 @@ Q_REQUIRED_RESULT
decltype(auto) transform(SC &&container, F function)
{
ResultContainer result;
- result.reserve(container.size());
+ reserve(result, container.size());
std::transform(std::begin(container), std::end(container), inserter(result), function);
return result;
}
diff --git a/tests/auto/algorithm/tst_algorithm.cpp b/tests/auto/algorithm/tst_algorithm.cpp
index 70088d8a20d..b5ce21c775b 100644
--- a/tests/auto/algorithm/tst_algorithm.cpp
+++ b/tests/auto/algorithm/tst_algorithm.cpp
@@ -27,6 +27,7 @@
#include <array>
#include <deque>
+#include <list>
#include <memory>
#include <unordered_map>
#include <valarray>
@@ -339,6 +340,25 @@ void tst_Algorithm::transform()
return s.getMember();
});
}
+ // target containers without reserve(...)
+ {
+ // std::vector -> std::deque
+ const std::vector<int> v({1, 2, 3, 4});
+ const std::deque<int> trans = Utils::transform<std::deque>(v, [](int i) { return i + 1; });
+ QCOMPARE(trans, std::deque<int>({2, 3, 4, 5}));
+ }
+ {
+ // std::vector -> std::list
+ const std::vector<int> v({1, 2, 3, 4});
+ const std::list<int> trans = Utils::transform<std::list>(v, [](int i) { return i + 1; });
+ QCOMPARE(trans, std::list<int>({2, 3, 4, 5}));
+ }
+ {
+ // std::vector -> std::set
+ const std::vector<int> v({1, 2, 3, 4});
+ 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}));
+ }
}
void tst_Algorithm::sort()
@@ -473,9 +493,10 @@ void tst_Algorithm::toRawPointer()
// different result container
const std::vector<Struct *> x2 = Utils::toRawPointer<std::vector>(v);
const QVector<Struct *> x3 = Utils::toRawPointer<QVector>(v);
+ const std::list<Struct *> x4 = Utils::toRawPointer<std::list>(v);
// different fully specified result container
- const std::vector<BaseStruct *> x4 = Utils::toRawPointer<std::vector<BaseStruct *>>(v);
- const QVector<BaseStruct *> x5 = Utils::toRawPointer<QVector<BaseStruct *>>(v);
+ const std::vector<BaseStruct *> x5 = Utils::toRawPointer<std::vector<BaseStruct *>>(v);
+ const QVector<BaseStruct *> x6 = Utils::toRawPointer<QVector<BaseStruct *>>(v);
}
void tst_Algorithm::toReferences()
@@ -496,6 +517,11 @@ void tst_Algorithm::toReferences()
std::vector<Struct> v;
const QList<std::reference_wrapper<Struct>> x = Utils::toReferences<QList>(v);
}
+ {
+ // std::vector -> std::list
+ std::vector<Struct> v;
+ const std::list<std::reference_wrapper<Struct>> x = Utils::toReferences<std::list>(v);
+ }
// toConstReference
{
// std::vector -> std::vector
@@ -513,6 +539,12 @@ void tst_Algorithm::toReferences()
const std::vector<Struct> v;
const QList<std::reference_wrapper<const Struct>> x = Utils::toConstReferences<QList>(v);
}
+ {
+ // std::vector -> std::list
+ const std::vector<Struct> v;
+ const std::list<std::reference_wrapper<const Struct>> x
+ = Utils::toConstReferences<std::list>(v);
+ }
}
QTEST_MAIN(tst_Algorithm)