Algorithm: Put declarations at top of file

It contains so much nowadays, and parts of it require internal
functions, so it became hard to actually find out what algorithms we
provide.

Put declarations of the "public" functions at the top of the file, to
make them more discoverable.

Change-Id: I99456e1023a6f39223d09a2936995b8fa6dc5cb0
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Eike Ziller
2019-05-13 14:26:11 +02:00
parent b6ea02d829
commit 50b12945b7

View File

@@ -48,6 +48,323 @@
namespace Utils namespace Utils
{ {
/////////////////////////
// anyOf
/////////////////////////
template<typename T, typename F>
bool anyOf(const T &container, F predicate);
template<typename T, typename R, typename S>
bool anyOf(const T &container, R (S::*predicate)() const);
template<typename T, typename R, typename S>
bool anyOf(const T &container, R S::*member);
/////////////////////////
// count
/////////////////////////
template<typename T, typename F>
int count(const T &container, F predicate);
/////////////////////////
// allOf
/////////////////////////
template<typename T, typename F>
bool allOf(const T &container, F predicate);
/////////////////////////
// erase
/////////////////////////
template<typename T, typename F>
void erase(T &container, F predicate);
/////////////////////////
// contains
/////////////////////////
template<typename T, typename F>
bool contains(const T &container, F function);
template<typename T, typename R, typename S>
bool contains(const T &container, R (S::*function)() const);
template<typename C, typename R, typename S>
bool contains(const C &container, R S::*member);
/////////////////////////
// findOr
/////////////////////////
template<typename C, typename F>
Q_REQUIRED_RESULT typename C::value_type findOr(const C &container,
typename C::value_type other,
F function);
template<typename T, typename R, typename S>
Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
typename T::value_type other,
R (S::*function)() const);
template<typename T, typename R, typename S>
Q_REQUIRED_RESULT typename T::value_type findOr(const T &container,
typename T::value_type other,
R S::*member);
/////////////////////////
// findOrDefault
/////////////////////////
template<typename C, typename F>
Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
typename C::value_type>
findOrDefault(const C &container, F function);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
typename C::value_type>
findOrDefault(const C &container, R (S::*function)() const);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT typename std::enable_if_t<std::is_copy_assignable<typename C::value_type>::value,
typename C::value_type>
findOrDefault(const C &container, R S::*member);
/////////////////////////
// indexOf
/////////////////////////
template<typename C, typename F>
Q_REQUIRED_RESULT int indexOf(const C &container, F function);
/////////////////////////
// maxElementOr
/////////////////////////
template<typename T>
typename T::value_type maxElementOr(const T &container, typename T::value_type other);
/////////////////////////
// filtered
/////////////////////////
template<typename C, typename F>
Q_REQUIRED_RESULT C filtered(const C &container, F predicate);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT C filtered(const C &container, R (S::*predicate)() const);
/////////////////////////
// partition
/////////////////////////
// Recommended usage:
// C hit;
// C miss;
// std::tie(hit, miss) = Utils::partition(container, predicate);
template<typename C, typename F>
Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, F predicate);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT std::tuple<C, C> partition(const C &container, R (S::*predicate)() const);
/////////////////////////
// filteredUnique
/////////////////////////
template<typename C>
Q_REQUIRED_RESULT C filteredUnique(const C &container);
/////////////////////////
// qobject_container_cast
/////////////////////////
template<class T, template<typename> class Container, typename Base>
Container<T> qobject_container_cast(const Container<Base> &container);
/////////////////////////
// static_container_cast
/////////////////////////
template<class T, template<typename> class Container, typename Base>
Container<T> static_container_cast(const Container<Base> &container);
/////////////////////////
// sort
/////////////////////////
template<typename Container>
inline void sort(Container &container);
template<typename Container, typename Predicate>
inline void sort(Container &container, Predicate p);
template<typename Container, typename R, typename S>
inline void sort(Container &container, R S::*member);
template<typename Container, typename R, typename S>
inline void sort(Container &container, R (S::*function)() const);
/////////////////////////
// reverseForeach
/////////////////////////
template<typename Container, typename Op>
inline void reverseForeach(const Container &c, const Op &operation);
/////////////////////////
// toReferences
/////////////////////////
template<template<typename...> class ResultContainer, typename SourceContainer>
auto toReferences(SourceContainer &sources);
template<typename SourceContainer>
auto toReferences(SourceContainer &sources);
/////////////////////////
// toConstReferences
/////////////////////////
template<template<typename...> class ResultContainer, typename SourceContainer>
auto toConstReferences(const SourceContainer &sources);
template<typename SourceContainer>
auto toConstReferences(const SourceContainer &sources);
/////////////////////////
// take
/////////////////////////
template<class C, typename P>
Q_REQUIRED_RESULT optional<typename C::value_type> take(C &container, P predicate);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT decltype(auto) take(C &container, R S::*member);
template<typename C, typename R, typename S>
Q_REQUIRED_RESULT decltype(auto) take(C &container, R (S::*function)() const);
/////////////////////////
// setUnionMerge
/////////////////////////
// Works like std::set_union but provides a merge function for items that match
// !(a > b) && !(b > a) which normally means that there is an "equal" match.
// It uses iterators to support move_iterators.
template<class InputIt1, class InputIt2, class OutputIt, class Merge, class Compare>
OutputIt setUnionMerge(InputIt1 first1,
InputIt1 last1,
InputIt2 first2,
InputIt2 last2,
OutputIt d_first,
Merge merge,
Compare comp);
template<class InputIt1, class InputIt2, class OutputIt, class Merge>
OutputIt setUnionMerge(
InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, OutputIt d_first, Merge merge);
template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge, class Compare>
OutputContainer setUnionMerge(InputContainer1 &&input1,
InputContainer2 &&input2,
Merge merge,
Compare comp);
template<class OutputContainer, class InputContainer1, class InputContainer2, class Merge>
OutputContainer setUnionMerge(InputContainer1 &&input1, InputContainer2 &&input2, Merge merge);
/////////////////////////
// usize / ssize
/////////////////////////
template<typename Container>
std::make_unsigned_t<typename Container::size_type> usize(Container container);
template<typename Container>
std::make_signed_t<typename Container::size_type> ssize(Container container);
/////////////////////////
// setUnion
/////////////////////////
template<typename InputIterator1, typename InputIterator2, typename OutputIterator, typename Compare>
OutputIterator set_union(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result,
Compare comp);
template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
OutputIterator set_union(InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
InputIterator2 last2,
OutputIterator result);
/////////////////////////
// transform
/////////////////////////
// function without result type deduction:
template<typename ResultContainer, // complete result container type
typename SC, // input container type
typename F> // function type
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
// function with result type deduction:
template<template<typename> class C, // result container type
typename SC, // input container type
typename F, // function type
typename Value = typename std::decay_t<SC>::value_type,
typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
typename ResultContainer = C<Result>>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
template<template<typename, typename> class C, // result container type
typename SC, // input container type
typename F, // function type
typename Value = typename std::decay_t<SC>::value_type,
typename Result = std::decay_t<std::result_of_t<F(Value &)>>,
typename ResultContainer = C<Result, std::allocator<Result>>>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function);
// member function without result type deduction:
template<template<typename...> class C, // result container type
typename SC, // input container type
typename R,
typename S>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
// member function with result type deduction:
template<typename ResultContainer, // complete result container type
typename SC, // input container type
typename R,
typename S>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R (S::*p)() const);
// member without result type deduction:
template<typename ResultContainer, // complete result container type
typename SC, // input container
typename R,
typename S>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
// member with result type deduction:
template<template<typename...> class C, // result container
typename SC, // input container
typename R,
typename S>
Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, R S::*p);
// same container types for input and output, const input
// function:
template<template<typename...> class C, // container type
typename F, // function type
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, F function);
// same container types for input and output, const input
// member function:
template<template<typename...> class C, // container type
typename R,
typename S,
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R (S::*p)() const);
// same container types for input and output, const input
// members:
template<template<typename...> class C, // container
typename R,
typename S,
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(const C<CArgs...> &container, R S::*p);
// same container types for input and output, non-const input
// function:
template<template<typename...> class C, // container type
typename F, // function type
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, F function);
// same container types for input and output, non-const input
// member function:
template<template<typename...> class C, // container type
typename R,
typename S,
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R (S::*p)() const);
// same container types for input and output, non-const input
// members:
template<template<typename...> class C, // container
typename R,
typename S,
typename... CArgs> // Arguments to SC
Q_REQUIRED_RESULT decltype(auto) transform(C<CArgs...> &container, R S::*p);
/////////////////////////////////////////////////////////////////////////////
//////// Implementations //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
////////////////// //////////////////
// anyOf // anyOf
///////////////// /////////////////
@@ -367,25 +684,23 @@ decltype(auto) transform(SC &&container, F function)
// function with result type deduction: // function with result type deduction:
template<template<typename> class C, // result container type template<template<typename> class C, // result container type
typename SC, // input container type typename SC, // input container type
typename F, // function type typename F, // function type
typename Value = typename std::decay_t<SC>::value_type, typename Value,
typename Result = std::decay_t<std::result_of_t<F(Value&)>>, typename Result,
typename ResultContainer = C<Result>> typename ResultContainer>
Q_REQUIRED_RESULT Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
decltype(auto) transform(SC &&container, F function)
{ {
return transform<ResultContainer>(std::forward<SC>(container), function); return transform<ResultContainer>(std::forward<SC>(container), function);
} }
template<template<typename, typename> class C, // result container type template<template<typename, typename> class C, // result container type
typename SC, // input container type typename SC, // input container type
typename F, // function type typename F, // function type
typename Value = typename std::decay_t<SC>::value_type, typename Value,
typename Result = std::decay_t<std::result_of_t<F(Value&)>>, typename Result,
typename ResultContainer = C<Result, std::allocator<Result>>> typename ResultContainer>
Q_REQUIRED_RESULT Q_REQUIRED_RESULT decltype(auto) transform(SC &&container, F function)
decltype(auto) transform(SC &&container, F function)
{ {
return transform<ResultContainer>(std::forward<SC>(container), function); return transform<ResultContainer>(std::forward<SC>(container), function);
} }