/* Copyright (C) 2013 VATSIM Community / contributors * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /*! \file */ #ifndef BLACKMISC_PREDICATES_H #define BLACKMISC_PREDICATES_H #include #include namespace BlackMisc { namespace Predicates { #ifdef Q_COMPILER_VARIADIC_TEMPLATES namespace Private { //! \internal template struct MemberEqual; template struct MemberEqual { M m; V v; MemberEqual(M m_, V v_) : m(m_), v(v_) {} bool operator()(const T &obj) const { return (obj.*m)() == v; } }; template struct MemberEqual { MemberEqual head; MemberEqual tail; MemberEqual(M m, V v, Tail... tail_) : head(m, v), tail(tail_...) {} bool operator()(const T &obj) const { return head(obj) && tail(obj); } }; //! \internal template struct MemberLess; template struct MemberLess { M m; MemberLess(M m_) : m(m_) {} bool operator()(const T &a, const T &b) const { return (a.*m)() < (b.*m)(); } bool isStable(const T &a, const T &b) const { return (a.*m)() != (b.*m)(); } }; template struct MemberLess { MemberLess head; MemberLess tail; MemberLess(M m, Tail... tail_) : head(m), tail(tail_...) {} bool operator()(const T &a, const T &b) const { return head.isStable(a, b) ? head(a, b) : tail(a, b); } }; } //namespace Private /*! * \brief Predicate which tests whether some member functions return some values. * \param vs Pairs of { pointer to member function of T, value to compare it against }. * \return A unary functor whose operator() which will perform the actual test. */ template typename Private::MemberEqual MemberEqual(Ts... vs) { return typename Private::MemberEqual(vs...); } /*! * \brief Predicate which compares the return values of some member functions of two objects. * \param vs Pointers to member functions of T. * \return A binary functor whose operator() which will perform the actual test. */ template typename Private::MemberLess MemberLess(Ts... vs) { return typename Private::MemberLess(vs...); } #else //!Q_COMPILER_VARIADIC_TEMPLATES template typename std::function MemberEqual(M1 m1, V1 v1) { return [ = ](const T & obj) -> bool { return (obj.*m1)() == v1; }; } template typename std::function MemberEqual(M1 m1, V1 v1, M2 m2, V2 v2) { return [ = ](const T & obj) -> bool { return (obj.*m1)() == v1 && (obj.*m2)() == v2; }; } template typename std::function MemberEqual(M1 m1, V1 v1, M2 m2, V2 v2, M3 m3, V3 v3) { return [ = ](const T & obj) -> bool { return (obj.*m1)() == v1 && (obj.*m2)() == v2 && (obj.*m3)() == v3; }; } template typename std::function MemberLess(M1 m1) { return [ = ](const T & a, const T & b) -> bool { return (a.*m1)() < (b.*m1)(); }; } template typename std::function MemberLess(M1 m1, M2 m2) { return [ = ](const T & a, const T & b) -> bool { if ((a.*m1)() != (b.*m1)()) return (a.*m1)() < (b.*m1)(); return (a.*m2)() < (b.*m2)(); }; } template typename std::function MemberLess(M1 m1, M2 m2, M3 m3) { return [ = ](const T & a, const T & b) -> bool { if ((a.*m1)() != (b.*m1)()) return (a.*m1)() < (b.*m1)(); if ((a.*m2)() != (b.*m2)()) return (a.*m2)() < (b.*m2)(); return (a.*m3)() < (b.*m3)(); }; } #endif //!Q_COMPILER_VARIADIC_TEMPLATES } //namespace Predicates } //namespace BlackMisc #endif //BLACKMISC_PREDICATES_H