/* 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 "index_sequence.h" #include #include #include namespace BlackMisc { namespace Predicates { namespace Private { //! \private template struct MemberEqual; //! \private template struct MemberEqual { M m; V v; MemberEqual(M m_, V v_) : m(m_), v(v_) {} template bool operator()(const T &obj) const { return (obj.*m)() == v; } }; //! \private template struct MemberEqual { MemberEqual head; MemberEqual tail; MemberEqual(M m, V v, Tail... tail_) : head(m, v), tail(tail_...) {} template bool operator()(const T &obj) const { return head(obj) && tail(obj); } }; //! \private template struct MemberLess; //! \private template struct MemberLess { M m; MemberLess(M m_) : m(m_) {} template bool operator()(const T &a, const T &b) const { return (a.*m)() < (b.*m)(); } template bool isStable(const T &a, const T &b) const { return (a.*m)() != (b.*m)(); } }; //! \private template struct MemberLess { MemberLess head; MemberLess tail; MemberLess(M m, Tail... tail_) : head(m), tail(tail_...) {} template bool operator()(const T &a, const T &b) const { return head.isStable(a, b) ? head(a, b) : tail(a, b); } }; //! \private template struct MemberTransform { M m; MemberTransform(M m_) : m(m_) {} auto operator()(const T &v) const -> decltype((v.*std::declval())()) { return (v.*m)(); } }; //! \private template struct MemberValid { M m; MemberValid(M m_) : m(m_) {} bool operator()(const T &v) const { return (v.*m)().isValid(); } }; //! \private template struct MemberIsAnyOf { M m; const C &c; MemberIsAnyOf(M m_, const C &c_) : m(m_), c(c_) {} bool operator()(const T &v) const { return c.contains((v.*m)()); } }; //! \private template struct Equals { const T m_value; template Equals(U &&value, int dummy) : m_value(std::forward(value)) { Q_UNUSED(dummy); } template bool operator ()(const U &other) const { return other == m_value; } }; } //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...); } /*! * Transformation function object which returns the value returned by one of it's argument member functions. * * A lambda would usually be easier, but it is difficult to directly return a lambda from a function * without C++14 deduced return types. */ template auto MemberTransform(R(T::*memberFunc)() const) -> Private::MemberTransform { return { memberFunc }; } /*! * Predicate which is true if the isValid() method of the value returned from one of its member functions returns true. * * A lambda would usually be easier, but it is difficult to directly return a lambda from a function * without C++14 deduced return types. */ template auto MemberValid(R(T::*memberFunc)() const) -> Private::MemberValid { return { memberFunc }; } /*! * Predicate which is true if the value returned by its argument's member function can be found in a captured container. * * A lambda would usually be easier, but it is difficult to directly return a lambda from a function * without C++14 deduced return types. * * \warning The container is captured by reference, so be careful that it remains valid for the lifetime of the predicate. */ template auto MemberIsAnyOf(R(T::*memberFunc)() const, const C &container) -> Private::MemberIsAnyOf { return { memberFunc, container }; } /*! * Predicate which is true if its argument compares equal with another, captured value. * * A lambda would usually be easier, but it is difficult to directly return a lambda from a function * without C++14 deduced return types. It is also a generic function object, which is only possible * with C++14 generic lambdas. */ template auto Equals(T &&value) -> Private::Equals::type> { return { std::forward(value), 0 }; } } //namespace Predicates } //namespace BlackMisc #endif //BLACKMISC_PREDICATES_H