refs #290 using a CRange of iterator adaptors to return from the primary predicate-based methods of CRangeBase without copying elements

This commit is contained in:
Mathew Sutcliffe
2014-07-03 20:06:13 +01:00
parent bd02c74ea8
commit 101c5a4f98
5 changed files with 65 additions and 26 deletions

View File

@@ -42,7 +42,7 @@ namespace BlackMisc
* Can take any suitable container class as its implementation at runtime.
*/
template <class T>
class CCollection : public CContainerBase<CCollection, T>
class CCollection : public CContainerBase<CCollection, T, Iterators::ConstForwardIterator<T>>
{
public:
//! \brief STL compatibility

View File

@@ -45,8 +45,8 @@ namespace BlackMisc
/*!
* \brief Base class for CCollection and CSequence adding mutating operations and CValueObject facility on top of CRangeBase.
*/
template <template <class> class C, class T>
class CContainerBase : public CValueObject, public CRangeBase<C<T>, T>
template <template <class> class C, class T, class CIt>
class CContainerBase : public CValueObject, public CRangeBase<C<T>, CIt>
{
public:
/*!

View File

@@ -8,34 +8,42 @@
#ifndef BLACKMISC_RANGE_H
#define BLACKMISC_RANGE_H
#include "valueobject.h"
#include "indexvariantmap.h"
#include "iterator.h"
#include "predicates.h"
#include "json.h"
#include <QtGlobal>
#include <algorithm>
#include <type_traits>
#include <iterator>
namespace BlackMisc
{
template <class> class CRange;
/*!
* Any container class with begin and end iterators can inherit from this CRTP class
* to gain some useful algorithms as member functions.
* \tparam Derived The most derived container class inheriting from this instantiation.
* \tparam CIt the const_iterator of Derived.
*/
template <class Derived, class T>
template <class Derived, class CIt>
class CRangeBase
{
public:
/*!
* Return a new container generated by applying some transformation function to all elements of this one.
*/
template <class F>
inline auto transform(F function) const
-> CRange<Iterators::TransformIterator<CIt, F>>;
/*!
* \brief Return a copy containing only those elements for which a given predicate returns true.
*/
template <class Predicate>
Derived findBy(Predicate p) const
{
Derived result = derived();
result.erase(std::remove_if(result.begin(), result.end(), [ = ](const typename Derived::value_type & value) { return !p(value); }), result.end());
return result;
}
inline auto findBy(Predicate p) const
-> CRange<Iterators::ConditionalIterator<CIt, Predicate>>;
/*!
* \brief Return a copy containing only those elements matching some particular key/value pair(s).
@@ -44,31 +52,28 @@ namespace BlackMisc
* \param keysValues Zero or more additional pairs of { pointer to member function of T, value to compare it against }.
*/
template <class K0, class V0, class... KeysValues>
Derived findBy(K0 k0, V0 v0, KeysValues... keysValues) const
{
return findBy(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
}
inline auto findBy(K0 k0, V0 v0, KeysValues... keysValues) const
-> CRange<Iterators::ConditionalIterator<CIt, decltype(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...))>>;
/*!
* \brief Return a copy containing only those elements matching a given value map.
*/
Derived findBy(const CIndexVariantMap &valueMap) const
{
return findBy([ & ](const T & value) { return value == valueMap; });
}
inline auto findBy(CIndexVariantMap valueMap) const
-> CRange<Iterators::ConditionalIterator<CIt, decltype(BlackMisc::Predicates::Equals(std::move(valueMap)))>>;
/*!
* \brief Return true if there is an element for which a given predicate returns true.
*/
template <class Predicate>
bool contains(Predicate p) const
bool containsBy(Predicate p) const
{
return std::any_of(derived().cbegin(), derived().cend(), p);
}
/*!
* \brief Return true if there is an element equal to given object. Uses the most efficient implementation available.
* \brief Return true if there is an element equal to given object. Uses the most efficient implementation available in the derived container.
*/
template <class T>
bool contains(const T &object) const
{
return derived().find(object) != derived().cend();
@@ -83,7 +88,7 @@ namespace BlackMisc
template <class K0, class V0, class... KeysValues>
bool contains(K0 k0, V0 v0, KeysValues... keysValues) const
{
return contains(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
return containsBy(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
}
private:
@@ -102,7 +107,7 @@ namespace BlackMisc
* during the lifetime of the range.
*/
template <class I>
class CRange : public CRangeBase<CRange<I>, typename std::iterator_traits<I>::value_type>
class CRange : public CRangeBase<CRange<I>, I>
{
public:
//! STL compatibility
@@ -213,6 +218,40 @@ namespace BlackMisc
return { container.cbegin(), container.cend() };
}
/*
* Member functions of CRangeBase template defined out of line, because they depend on CRange etc.
*/
template <class Derived, class CIt>
template <class F>
auto CRangeBase<Derived, CIt>::transform(F function) const
-> CRange<Iterators::TransformIterator<CIt, F>>
{
return makeRange(Iterators::makeTransformIterator(derived().cbegin(), function), derived().cend());
}
template <class Derived, class CIt>
template <class Predicate>
auto CRangeBase<Derived, CIt>::findBy(Predicate p) const
-> CRange<Iterators::ConditionalIterator<CIt, Predicate>>
{
return makeRange(makeConditionalIterator(derived().cbegin(), derived().cend(), p), derived().cend());
}
template <class Derived, class CIt>
template <class K0, class V0, class... KeysValues>
auto CRangeBase<Derived, CIt>::findBy(K0 k0, V0 v0, KeysValues... keysValues) const
-> CRange<Iterators::ConditionalIterator<CIt, decltype(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...))>>
{
return findBy(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
}
template <class Derived, class CIt>
auto CRangeBase<Derived, CIt>::findBy(CIndexVariantMap valueMap) const
-> CRange<Iterators::ConditionalIterator<CIt, decltype(BlackMisc::Predicates::Equals(std::move(valueMap)))>>
{
return findBy(BlackMisc::Predicates::Equals(std::move(valueMap)));
}
}
#endif // guard

View File

@@ -28,7 +28,7 @@ namespace BlackMisc
* Can take any suitable container class as its implementation at runtime.
*/
template <class T>
class CSequence : public CContainerBase<CSequence, T>
class CSequence : public CContainerBase<CSequence, T, Iterators::ConstBidirectionalIterator<T>>
{
public:
//! \brief STL compatibility

View File

@@ -26,7 +26,7 @@ namespace BlackSim
*/
bool CAircraftCfgEntriesList::containsModeWithTitle(const QString &title, Qt::CaseSensitivity caseSensitivity)
{
return this->contains([ = ](const CAircraftCfgEntries & entries) -> bool
return this->containsBy([ = ](const CAircraftCfgEntries & entries) -> bool
{ return title.compare(entries.getTitle(), caseSensitivity) == 0; });
}