Utils: Make algorithms take more containers

Change-Id: I05bd1052bbc2c6481fdec8a3763d9ae4f3dc8f44
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Tobias Hunger
2017-11-27 11:31:15 +01:00
parent 750493a0eb
commit 566b118a87
2 changed files with 44 additions and 27 deletions

View File

@@ -45,19 +45,19 @@ namespace Utils
template<typename T, typename R, typename S> template<typename T, typename R, typename S>
bool anyOf(const T &container, R (S::*predicate)() const) bool anyOf(const T &container, R (S::*predicate)() const)
{ {
return std::any_of(container.begin(), container.end(), std::mem_fn(predicate)); return std::any_of(std::begin(container), std::end(container), std::mem_fn(predicate));
} }
template<typename T, typename F> template<typename T, typename F>
bool anyOf(const T &container, F predicate) bool anyOf(const T &container, F predicate)
{ {
return std::any_of(container.begin(), container.end(), predicate); return std::any_of(std::begin(container), std::end(container), predicate);
} }
template<typename T, typename F> template<typename T, typename F>
int count(const T &container, F predicate) int count(const T &container, F predicate)
{ {
return std::count_if(container.begin(), container.end(), predicate); return std::count_if(std::begin(container), std::end(container), predicate);
} }
////////////////// //////////////////
@@ -66,27 +66,28 @@ int count(const T &container, F predicate)
template<typename T, typename F> template<typename T, typename F>
bool allOf(const T &container, F predicate) bool allOf(const T &container, F predicate)
{ {
return std::all_of(container.begin(), container.end(), predicate); return std::all_of(std::begin(container), std::end(container), predicate);
} }
////////////////// //////////////////
// erase // erase
///////////////// /////////////////
template<typename T, typename F> template<typename T, typename F>
void erase(QList<T> &container, F predicate) void erase(T &container, F predicate)
{ {
container.erase(std::remove_if(container.begin(), container.end(), predicate), container.erase(std::remove_if(std::begin(container), std::end(container), predicate),
container.end()); std::end(container));
} }
////////////////// //////////////////
// contains // contains
///////////////// /////////////////
template<typename T, typename F> template<typename T, typename F>
bool contains(const T &container, F function) bool contains(const T &container, F function)
{ {
typename T::const_iterator end = container.end(); typename T::const_iterator begin = std::begin(container);
typename T::const_iterator begin = container.begin(); typename T::const_iterator end = std::end(container);
typename T::const_iterator it = std::find_if(begin, end, function); typename T::const_iterator it = std::find_if(begin, end, function);
return it != end; return it != end;
@@ -98,8 +99,8 @@ bool contains(const T &container, F function)
template<typename T, typename F> template<typename T, typename F>
typename T::value_type findOr(const T &container, typename T::value_type other, F function) typename T::value_type findOr(const T &container, typename T::value_type other, F function)
{ {
typename T::const_iterator end = container.end(); typename T::const_iterator begin = std::begin(container);
typename T::const_iterator begin = container.begin(); typename T::const_iterator end = std::end(container);
typename T::const_iterator it = std::find_if(begin, end, function); typename T::const_iterator it = std::find_if(begin, end, function);
if (it == end) if (it == end)
@@ -117,8 +118,8 @@ typename T::value_type findOr(const T &container, typename T::value_type other,
template<typename T, typename F> template<typename T, typename F>
int indexOf(const T &container, F function) int indexOf(const T &container, F function)
{ {
typename T::const_iterator end = container.end(); typename T::const_iterator begin = std::begin(container);
typename T::const_iterator begin = container.begin(); typename T::const_iterator end = std::end(container);
typename T::const_iterator it = std::find_if(begin, end, function); typename T::const_iterator it = std::find_if(begin, end, function);
if (it == end) if (it == end)
@@ -145,8 +146,8 @@ typename T::value_type findOrDefault(const T &container, R (S::*function)() cons
template<typename T> template<typename T>
typename T::value_type maxElementOr(const T &container, typename T::value_type other) typename T::value_type maxElementOr(const T &container, typename T::value_type other)
{ {
typename T::const_iterator end = container.end(); typename T::const_iterator begin = std::begin(container);
typename T::const_iterator begin = container.begin(); typename T::const_iterator end = std::end(container);
typename T::const_iterator it = std::max_element(begin, end); typename T::const_iterator it = std::max_element(begin, end);
if (it == end) if (it == end)
@@ -299,7 +300,7 @@ Q_REQUIRED_RESULT
C filtered(const C &container, F predicate) C filtered(const C &container, F predicate)
{ {
C out; C out;
std::copy_if(container.begin(), container.end(), std::copy_if(std::begin(container), std::end(container),
inserter(out), predicate); inserter(out), predicate);
return out; return out;
} }
@@ -309,7 +310,7 @@ Q_REQUIRED_RESULT
C filtered(const C &container, R (S::*predicate)() const) C filtered(const C &container, R (S::*predicate)() const)
{ {
C out; C out;
std::copy_if(container.begin(), container.end(), std::copy_if(std::begin(container), std::end(container),
inserter(out), std::mem_fn(predicate)); inserter(out), std::mem_fn(predicate));
return out; return out;
} }
@@ -361,8 +362,8 @@ C filteredUnique(const C &container)
QSet<typename C::value_type> seen; QSet<typename C::value_type> seen;
int setSize = 0; int setSize = 0;
auto endIt = container.end(); auto endIt = std::end(container);
for (auto it = container.begin(); it != endIt; ++it) { for (auto it = std::begin(container); it != endIt; ++it) {
seen.insert(*it); seen.insert(*it);
if (setSize == seen.size()) // unchanged size => was already seen if (setSize == seen.size()) // unchanged size => was already seen
continue; continue;
@@ -391,35 +392,37 @@ Container<T> qobject_container_cast(const Container<Base> &container)
// sort // sort
///////////////// /////////////////
template <typename Container> template <typename Container>
inline void sort(Container &c) inline void sort(Container &container)
{ {
std::sort(c.begin(), c.end()); std::sort(std::begin(container), std::end(container));
} }
template <typename Container, typename Predicate> template <typename Container, typename Predicate>
inline void sort(Container &c, Predicate p) inline void sort(Container &container, Predicate p)
{ {
std::sort(c.begin(), c.end(), p); std::sort(std::begin(container), std::end(container), p);
} }
// pointer to member // pointer to member
template <typename Container, typename R, typename S> template <typename Container, typename R, typename S>
inline void sort(Container &c, R S::*member) inline void sort(Container &container, R S::*member)
{ {
auto f = std::mem_fn(member); auto f = std::mem_fn(member);
using const_ref = typename Container::const_reference; using const_ref = typename Container::const_reference;
std::sort(c.begin(), c.end(), [&f](const_ref a, const_ref b) { std::sort(std::begin(container), std::end(container),
[&f](const_ref a, const_ref b) {
return f(a) < f(b); return f(a) < f(b);
}); });
} }
// pointer to member function // pointer to member function
template <typename Container, typename R, typename S> template <typename Container, typename R, typename S>
inline void sort(Container &c, R (S::*function)() const) inline void sort(Container &container, R (S::*function)() const)
{ {
auto f = std::mem_fn(function); auto f = std::mem_fn(function);
using const_ref = typename Container::const_reference; using const_ref = typename Container::const_reference;
std::sort(c.begin(), c.end(), [&f](const_ref a, const_ref b) { std::sort(std::begin(container), std::end(container),
[&f](const_ref a, const_ref b) {
return f(a) < f(b); return f(a) < f(b);
}); });
} }

View File

@@ -25,6 +25,8 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <valarray>
#include <QtTest> #include <QtTest>
class tst_Algorithm : public QObject class tst_Algorithm : public QObject
@@ -151,6 +153,18 @@ void tst_Algorithm::sort()
QList<Struct *> s6({&arr2[0], &arr2[1], &arr2[2]}); QList<Struct *> s6({&arr2[0], &arr2[1], &arr2[2]});
Utils::sort(s6, &Struct::member); Utils::sort(s6, &Struct::member);
QCOMPARE(s6, QList<Struct *>({&arr2[1], &arr2[2], &arr2[0]})); QCOMPARE(s6, QList<Struct *>({&arr2[1], &arr2[2], &arr2[0]}));
// std::array:
std::array<int, 4> array = {{4, 10, 8, 1}};
Utils::sort(array);
std::array<int, 4> arrayResult = {{1, 4, 8, 10}};
QCOMPARE(array, arrayResult);
// valarray (no begin/end member functions):
std::valarray<int> valarray(array.data(), array.size());
std::valarray<int> valarrayResult(arrayResult.data(), arrayResult.size());
Utils::sort(valarray);
QCOMPARE(valarray.size(), valarrayResult.size());
for (size_t i = 0; i < valarray.size(); ++i)
QCOMPARE(valarray[i], valarrayResult[i]);
} }
QTEST_MAIN(tst_Algorithm) QTEST_MAIN(tst_Algorithm)