From db453a623239e55dafdba3573abc130b1e30f385 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 3 Jul 2014 19:04:13 +0100 Subject: [PATCH] refs #290 added some new predicates and transform functions to use in combination with the iterator adaptors. This required refactoring index_sequence out of tuple_private.h so it could be used by the predicates. --- src/blackmisc/index_sequence.h | 46 ++++++++++++++++++ src/blackmisc/predicates.h | 88 +++++++++++++++++++++++++++++++++- src/blackmisc/tuple_private.h | 21 +------- 3 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 src/blackmisc/index_sequence.h diff --git a/src/blackmisc/index_sequence.h b/src/blackmisc/index_sequence.h new file mode 100644 index 000000000..5ed4d932d --- /dev/null +++ b/src/blackmisc/index_sequence.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2014 VATSIM Community / authors + * 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/. */ + +#ifndef BLACKMISC_INDEX_SEQUENCE_H +#define BLACKMISC_INDEX_SEQUENCE_H + +#include +#include + +namespace BlackMisc +{ + namespace Private + { + + // Inhibit doxygen warnings about missing documentation + //! \cond PRIVATE + + // Our own implementation of std::index_sequence (because not implemented by MSVC2013) + template + struct index_sequence + { + static const size_t size = sizeof...(Is); + typedef std::tuple...> tuple_type; + }; + template + struct GenSequence + { + typedef typename GenSequence::type type; + }; + template + struct GenSequence + { + typedef index_sequence type; + }; + template + using make_index_sequence = typename GenSequence<0, C>::type; + + //! \endcond + + } // namespace Private + +} // namespace BlackMisc + +#endif // guard diff --git a/src/blackmisc/predicates.h b/src/blackmisc/predicates.h index 8f42b9fff..65aad0205 100644 --- a/src/blackmisc/predicates.h +++ b/src/blackmisc/predicates.h @@ -10,8 +10,10 @@ #ifndef BLACKMISC_PREDICATES_H #define BLACKMISC_PREDICATES_H -#include +#include "index_sequence.h" #include +#include +#include namespace BlackMisc { @@ -63,6 +65,39 @@ namespace BlackMisc 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) : m_value(std::forward(value)) {} + template bool operator ()(const U &other) const { return other == m_value; } + }; + } //namespace Private /*! @@ -87,6 +122,57 @@ namespace BlackMisc 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) }; + } + } //namespace Predicates } //namespace BlackMisc diff --git a/src/blackmisc/tuple_private.h b/src/blackmisc/tuple_private.h index b943eadbe..4a0574302 100644 --- a/src/blackmisc/tuple_private.h +++ b/src/blackmisc/tuple_private.h @@ -6,6 +6,7 @@ #ifndef BLACKMISC_TUPLE_PRIVATE_H #define BLACKMISC_TUPLE_PRIVATE_H +#include "index_sequence.h" #include #include #include @@ -55,26 +56,6 @@ namespace BlackMisc return 0; } - // Our own implementation of std::index_sequence (because not implemented by MSVC2013) - template - struct index_sequence - { - static const size_t size = sizeof...(Is); - typedef std::tuple...> tuple_type; - }; - template - struct GenSequence - { - typedef typename GenSequence::type type; - }; - template - struct GenSequence - { - typedef index_sequence type; - }; - template - using make_index_sequence = typename GenSequence<0, C>::type; - // Create an index_sequence containing indices which match a given predicate. template struct GenSequenceOnPredicate;