mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-16 02:06:08 +08:00
refs #698 Avoid recursive templates by using C++14 generic lambda.
This commit is contained in:
@@ -12,6 +12,8 @@
|
|||||||
#ifndef BLACKMISC_ALGORITHM_H
|
#ifndef BLACKMISC_ALGORITHM_H
|
||||||
#define BLACKMISC_ALGORITHM_H
|
#define BLACKMISC_ALGORITHM_H
|
||||||
|
|
||||||
|
#include "integersequence.h"
|
||||||
|
|
||||||
#include <QThreadStorage>
|
#include <QThreadStorage>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -138,6 +140,50 @@ namespace BlackMisc
|
|||||||
"BlackMisc::topologicallySortedInsert", "Cyclic less-than relation detected (not a partial ordering)");
|
"BlackMisc::topologicallySortedInsert", "Cyclic less-than relation detected (not a partial ordering)");
|
||||||
container.insert(rit.base(), std::forward<T>(value));
|
container.insert(rit.base(), std::forward<T>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
//! \private
|
||||||
|
template <typename T, typename F, size_t... Is>
|
||||||
|
void tupleForEachImpl(T &&tuple, F &&visitor, index_sequence<Is...>)
|
||||||
|
{
|
||||||
|
// parameter pack swallow idiom
|
||||||
|
static_cast<void>(std::initializer_list<int>
|
||||||
|
{
|
||||||
|
(static_cast<void>(std::forward<F>(visitor)(std::get<Is>(std::forward<T>(tuple)))), 0)...
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//! \private
|
||||||
|
template <typename T, typename F, size_t... Is>
|
||||||
|
void tupleForEachPairImpl(T &&tuple, F &&visitor, index_sequence<Is...>)
|
||||||
|
{
|
||||||
|
// parameter pack swallow idiom
|
||||||
|
static_cast<void>(std::initializer_list<int>
|
||||||
|
{
|
||||||
|
(static_cast<void>(std::forward<F>(visitor)(std::get<Is * 2>(std::forward<T>(tuple)), std::get<Is * 2 + 1>(std::forward<T>(tuple)))), 0)...
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Invoke a visitor function on each element of a tuple in order.
|
||||||
|
*/
|
||||||
|
template <typename T, typename F>
|
||||||
|
void tupleForEach(T &&tuple, F &&visitor)
|
||||||
|
{
|
||||||
|
using seq = Private::make_index_sequence<std::tuple_size<std::decay_t<T>>::value>;
|
||||||
|
return Private::tupleForEachImpl(std::forward<T>(tuple), std::forward<F>(visitor), seq());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Invoke a visitor function on each pair of elements of a tuple in order.
|
||||||
|
*/
|
||||||
|
template <typename T, typename F>
|
||||||
|
void tupleForEachPair(T &&tuple, F &&visitor)
|
||||||
|
{
|
||||||
|
using seq = Private::make_index_sequence<std::tuple_size<std::decay_t<T>>::value / 2>;
|
||||||
|
return Private::tupleForEachPairImpl(std::forward<T>(tuple), std::forward<F>(visitor), seq());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#define BLACKMISC_PREDICATES_H
|
#define BLACKMISC_PREDICATES_H
|
||||||
|
|
||||||
#include "integersequence.h"
|
#include "integersequence.h"
|
||||||
|
#include "algorithm.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -29,69 +30,6 @@ namespace BlackMisc
|
|||||||
|
|
||||||
namespace Private
|
namespace Private
|
||||||
{
|
{
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class...> struct MemberEqual;
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M, class V> struct MemberEqual<M, V>
|
|
||||||
{
|
|
||||||
M m;
|
|
||||||
V v;
|
|
||||||
MemberEqual(M m_, V v_) : m(m_), v(v_) {}
|
|
||||||
template <class T> bool operator()(const T &obj) const { return (obj.*m)() == v; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M, class V, class... Tail> struct MemberEqual<M, V, Tail...>
|
|
||||||
{
|
|
||||||
MemberEqual<M, V> head;
|
|
||||||
MemberEqual<Tail...> tail;
|
|
||||||
MemberEqual(M m, V v, Tail... tail_) : head(m, v), tail(tail_...) {}
|
|
||||||
template <class T> bool operator()(const T &obj) const { return head(obj) && tail(obj); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class...> struct MemberLess;
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M> struct MemberLess<M>
|
|
||||||
{
|
|
||||||
M m;
|
|
||||||
MemberLess(M m_) : m(m_) {}
|
|
||||||
template <class T> bool operator()(const T &a, const T &b) const { return (a.*m)() < (b.*m)(); }
|
|
||||||
template <class T> bool isStable(const T &a, const T &b) const { return (a.*m)() != (b.*m)(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M, class... Tail> struct MemberLess<M, Tail...>
|
|
||||||
{
|
|
||||||
MemberLess<M> head;
|
|
||||||
MemberLess<Tail...> tail;
|
|
||||||
MemberLess(M m, Tail... tail_) : head(m), tail(tail_...) {}
|
|
||||||
template <class T> bool operator()(const T &a, const T &b) const { return head.isStable(a, b) ? head(a, b) : tail(a, b); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class...> struct EqualsByMembers;
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M> struct EqualsByMembers<M>
|
|
||||||
{
|
|
||||||
M m;
|
|
||||||
EqualsByMembers(M m_) : m(m_) {}
|
|
||||||
template <class T> bool operator()(const T &a, const T &b) const { return (a.*m)() == (b.*m)(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
|
||||||
template <class M, class... Tail> struct EqualsByMembers<M, Tail...>
|
|
||||||
{
|
|
||||||
EqualsByMembers<M> head;
|
|
||||||
EqualsByMembers<Tail...> tail;
|
|
||||||
EqualsByMembers(M m, Tail... tail_) : head(m), tail(tail_...) {}
|
|
||||||
template <class T> bool operator()(const T &a, const T &b) const { return head(a, b) && tail(a, b); }
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \private
|
//! \private
|
||||||
struct Matches
|
struct Matches
|
||||||
{
|
{
|
||||||
@@ -99,8 +37,7 @@ namespace BlackMisc
|
|||||||
Matches(const CPropertyIndexVariantMap &map) : m_map(map) {}
|
Matches(const CPropertyIndexVariantMap &map) : m_map(map) {}
|
||||||
template <class T> bool operator()(const T &value) const;
|
template <class T> bool operator()(const T &value) const;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
} //namespace Private
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Predicate which tests whether some member functions return some values.
|
* Predicate which tests whether some member functions return some values.
|
||||||
@@ -108,9 +45,14 @@ namespace BlackMisc
|
|||||||
* \return A unary functor whose operator() which will perform the actual test.
|
* \return A unary functor whose operator() which will perform the actual test.
|
||||||
*/
|
*/
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
Private::MemberEqual<Ts...> MemberEqual(Ts... vs)
|
auto MemberEqual(Ts... vs)
|
||||||
{
|
{
|
||||||
return { vs... };
|
return [vs...](const auto &object)
|
||||||
|
{
|
||||||
|
bool equal = true;
|
||||||
|
tupleForEachPair(std::make_tuple(vs...), [ & ](auto member, const auto &value) { equal = equal && (object.*member)() == value; });
|
||||||
|
return equal;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -119,9 +61,19 @@ namespace BlackMisc
|
|||||||
* \return A binary functor whose operator() which will perform the actual test.
|
* \return A binary functor whose operator() which will perform the actual test.
|
||||||
*/
|
*/
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
Private::MemberLess<Ts...> MemberLess(Ts... vs)
|
auto MemberLess(Ts... vs)
|
||||||
{
|
{
|
||||||
return { vs... };
|
return [vs...](const auto &a, const auto &b)
|
||||||
|
{
|
||||||
|
bool less = true;
|
||||||
|
bool greater = false;
|
||||||
|
tupleForEach(std::make_tuple(vs...), [ & ](auto member)
|
||||||
|
{
|
||||||
|
less = less && ! greater && (a.*member)() < (b.*member)();
|
||||||
|
greater = (b.*member)() < (a.*member)();
|
||||||
|
});
|
||||||
|
return less;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -165,9 +117,14 @@ namespace BlackMisc
|
|||||||
* Returns a predicate that returns true if its arguments compare equal to each other, considering only the captured members.
|
* Returns a predicate that returns true if its arguments compare equal to each other, considering only the captured members.
|
||||||
*/
|
*/
|
||||||
template <class... Ts>
|
template <class... Ts>
|
||||||
Private::EqualsByMembers<Ts...> EqualsByMembers(Ts... vs)
|
auto EqualsByMembers(Ts... vs)
|
||||||
{
|
{
|
||||||
return { vs... };
|
return [vs...](const auto &a, const auto &b)
|
||||||
|
{
|
||||||
|
bool equal = true;
|
||||||
|
tupleForEach(std::make_tuple(vs...), [ & ](auto member) { equal = equal && (a.*member)() == (b.*member)(); });
|
||||||
|
return equal;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
Reference in New Issue
Block a user