diff options
-rw-r--r-- | src/libs/utils/algorithm.h | 48 | ||||
-rw-r--r-- | tests/auto/algorithm/tst_algorithm.cpp | 36 |
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) |