Use C++14 features to simplify our container base classes

Summary: Using C++14 function return type deduction we can simplify the CRTP in CContainerBase etc.

Reviewers: #swift_developers, rwinklmeier

Reviewed By: #swift_developers, rwinklmeier

Subscribers: jenkins

Tags: #swift_pilot_client

Differential Revision: https://dev.swift-project.org/D65
This commit is contained in:
Mathew Sutcliffe
2017-11-23 21:59:08 +00:00
parent c553d24d0e
commit 921ef30eda
5 changed files with 58 additions and 54 deletions

View File

@@ -44,48 +44,49 @@ namespace BlackMisc
* 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 CIt>
template <class Derived>
class CRangeBase
{
using value_type = typename std::iterator_traits<CIt>::value_type;
using const_reference = typename std::iterator_traits<CIt>::reference;
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>>;
inline auto transform(F function) const;
//! Return a copy containing only those elements for which a given predicate returns true.
template <class Predicate>
inline auto findBy(Predicate p) const
-> CRange<Iterators::ConditionalIterator<CIt, Predicate>>;
inline auto findBy(Predicate p) const;
//! Return a copy containing only those elements matching some particular key/value pair(s).
//! \param k0 A pointer to a member function of T.
//! \param v0 A value to compare against the value returned by k0.
//! \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>
inline auto findBy(K0 k0, V0 v0, KeysValues... keysValues) const
-> CRange<Iterators::ConditionalIterator<CIt, decltype(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...))>>;
inline auto findBy(K0 k0, V0 v0, KeysValues... keysValues) const;
//! Return a reference to the first element for which a given predicate returns true. Undefined if there is none.
template <class Predicate>
const_reference findFirstBy(Predicate p) const { return findBy(p).front(); }
const auto &findFirstBy(Predicate p) const { return findBy(p).front(); }
//! Return a reference to the first element matching some particular key/value pair(s). Undefined if there is none.
template <class K, class V>
const_reference findFirstBy(K key, V value) const { return findBy(key, value).front(); }
const auto &findFirstBy(K key, V value) const { return findBy(key, value).front(); }
//! Return a copy of the first element for which a given predicate returns true, or a default value if there is none.
template <class Predicate, class Value>
auto findFirstByOrDefault(Predicate p, const Value &def) const { return findBy(p).frontOrDefault(def); }
//! Return a copy of the first element for which a given predicate returns true, or a default value if there is none.
template <class Predicate>
value_type findFirstByOrDefault(Predicate p, const value_type &def = value_type{}) const { return findBy(p).frontOrDefault(def); }
auto findFirstByOrDefault(Predicate p) const { return findBy(p).frontOrDefault(); }
//! Return a copy of the first element matching some particular key/value pair(s), or a default value if there is none.
template <class K, class V>
value_type findFirstByOrDefault(K key, V value, const value_type &def = value_type{}) const { return findBy(key, value).frontOrDefault(def); }
template <class K, class V, class Value>
auto findFirstByOrDefault(K key, V value, const Value &def) const { return findBy(key, value).frontOrDefault(def); }
//! Return a copy of the first element matching some particular key/value pair(s), or a default value if there is none.
template <class T, class K, class V>
auto findFirstByOrDefault(K T::* key, V value) const { return findBy(key, value).frontOrDefault(); }
//! Return true if there is an element for which a given predicate returns true.
template <class Predicate>
@@ -167,7 +168,7 @@ namespace BlackMisc
* during the lifetime of the range.
*/
template <class I>
class CRange : public CRangeBase<CRange<I>, I>
class CRange : public CRangeBase<CRange<I>>
{
public:
//! STL compatibility
@@ -340,26 +341,23 @@ namespace BlackMisc
/*
* Member functions of CRangeBase template defined out of line, because they depend on CRange etc.
*/
template <class Derived, class CIt>
template <class Derived>
template <class F>
auto CRangeBase<Derived, CIt>::transform(F function) const
-> CRange<Iterators::TransformIterator<CIt, F>>
auto CRangeBase<Derived>::transform(F function) const
{
return makeRange(Iterators::makeTransformIterator(derived().cbegin(), function), derived().cend());
}
template <class Derived, class CIt>
template <class Derived>
template <class Predicate>
auto CRangeBase<Derived, CIt>::findBy(Predicate p) const
-> CRange<Iterators::ConditionalIterator<CIt, Predicate>>
auto CRangeBase<Derived>::findBy(Predicate p) const
{
return makeRange(Iterators::makeConditionalIterator(derived().cbegin(), derived().cend(), p), derived().cend());
}
template <class Derived, class CIt>
template <class Derived>
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...))>>
auto CRangeBase<Derived>::findBy(K0 k0, V0 v0, KeysValues... keysValues) const
{
return findBy(BlackMisc::Predicates::MemberEqual(k0, v0, keysValues...));
}