32 #include <type_traits>
35 #include <QStringList>
36 #include <boost/optional.hpp>
58 template<
typename T1,
typename T2,
template<
typename U>
class Container,
typename F>
66 auto i1 = begin (c1), e1 = end (c1);
67 auto i2 = begin (c2), e2 = end (c2);
68 for ( ; i1 != e1 && i2 != e2; ++i1, ++i2)
69 result.push_back (f (*i1, *i2));
73 template<
typename T1,
typename T2,
74 template<
typename U>
class Container,
75 template<
typename U1,
typename U2>
class Pair = QPair>
76 auto Zip (
const Container<T1>& c1,
const Container<T2>& c2) -> Container<Pair<T1, T2>>
79 [] (
const T1& t1,
const T2& t2) -> Pair<T1, T2>
80 {
return { t1, t2}; });
85 template<
typename Res,
typename T>
86 void Append (Res& result, T&& val, decltype (result.push_back (std::forward<T> (val)))* =
nullptr)
88 result.push_back (std::forward<T> (val));
91 template<
typename Res,
typename T>
92 void Append (Res& result, T&& val, decltype (result.insert (std::forward<T> (val)))* =
nullptr)
94 result.insert (std::forward<T> (val));
97 template<
typename T,
typename F>
103 template<
typename T,
typename F>
109 template<
typename T,
typename F>
112 return IsInvokableWithConstImpl<std::decay_t<T>, F> (0);
121 template<
template<
typename...>
class Container,
typename... Args>
133 template<
typename F,
typename Cont>
136 using Ret_t = decltype (
Invoke (std::declval<F> (), *std::declval<Cont> ().begin ()));
137 return std::is_same<void, Ret_t>::value;
143 template<
typename U>
class Container,
145 typename = std::enable_if_t<detail::IsSimpleContainer<Container<T>> ()>,
148 auto Map (
const Container<T>& c, F f)
150 WrapType_t<Container<std::decay_t<decltype (
Invoke (f, *c.begin ()))>>> result;
159 template<
typename>
class ResultCont =
QList,
160 typename = std::enable_if_t<!detail::IsSimpleContainer<Container> ()>,
161 typename = std::enable_if_t<!detail::DoesReturnVoid<F, Container> ()>
163 auto Map (
const Container& c, F f)
165 WrapType_t<ResultCont<std::decay_t<decltype (
Invoke (f, *c.begin ()))>>> cont;
174 typename = std::enable_if_t<detail::DoesReturnVoid<F, Container> ()>
176 auto Map (
const Container& c, F f)
185 typename = std::enable_if_t<detail::DoesReturnVoid<F, Container> ()>
187 auto Map (Container& c, F f)
193 template<
typename T,
template<
typename U>
class Container,
typename F>
194 Container<T>
Filter (
const Container<T>& c, F f)
197 for (
const auto& item : c)
203 template<
template<
typename>
class Container,
typename T>
204 Container<T>
Concat (
const Container<Container<T>>& containers)
207 for (
const auto& cont : containers)
208 std::copy (cont.begin (), cont.end (), std::back_inserter (result));
212 template<
template<
typename...>
class Container,
typename... ContArgs>
213 auto Concat (
const Container<ContArgs...>& containers) -> std::decay_t<decltype (*containers.begin ())>
215 std::decay_t<decltype (*containers.begin ())> result;
216 for (
const auto& cont : containers)
217 std::copy (cont.begin (), cont.end (), std::back_inserter (result));
221 template<
typename Cont,
typename F>
222 auto ConcatMap (Cont&& c, F&& f) -> decltype (
Concat (
Map (std::forward<Cont> (c), std::forward<F> (f))))
224 return Concat (
Map (std::forward<Cont> (c), std::forward<F> (f)));
227 template<
template<
typename>
class Container,
typename T>
228 Container<Container<T>>
SplitInto (
size_t numChunks,
const Container<T>& container)
230 Container<Container<T>> result;
232 const size_t chunkSize = container.size () / numChunks;
233 for (
size_t i = 0; i < numChunks; ++i)
235 Container<T> subcont;
236 const auto start = container.begin () + chunkSize * i;
237 const auto end = start + chunkSize;
238 std::copy (start, end, std::back_inserter (subcont));
239 result.push_back (subcont);
242 const auto lastStart = container.begin () + chunkSize * numChunks;
243 const auto lastEnd = container.end ();
244 std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
249 template<
template<
typename Pair,
typename... Rest>
class Cont, template<typename K, typename V> class Pair, typename K, typename V, typename KV, typename... Rest>
250 boost::optional<V>
Lookup (const KV& key, const Cont<Pair<K, V>, Rest...>& cont)
252 for (
const auto& pair : cont)
253 if (pair.first == key)
259 template<
typename Cont>
262 std::sort (cont.begin (), cont.end ());
266 const auto Id = [] (
const auto& t) {
return t; };
271 return [r] (
const auto& left,
const auto& right) {
return Invoke (r, left) <
Invoke (r, right); };
274 const auto Apply = [] (
const auto& t) {
return t (); };
276 const auto Fst = [] (
const auto& pair) {
return pair.first; };
278 const auto Snd = [] (
const auto& pair) {
return pair.second; };
283 return [f = std::forward<F> (f)] (
const auto& pair) {
return Invoke (f, pair.first); };
289 return [f = std::forward<F> (f)] (
const auto& pair) {
return Invoke (f, pair.second); };
295 return [f = std::move (f)] (
auto&& left,
auto&& right)
297 return f (std::forward<decltype (right)> (right),
298 std::forward<decltype (left)> (left));
auto Map(const Container< T > &c, F f)
constexpr bool IsInvokableWithConstImpl(std::result_of_t< F(const T &)> *)
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 >>
auto ZipWith(const Container< T1 > &c1, const Container< T2 > &c2, F f) -> WrapType_t< Container< std::decay_t< std::result_of_t< F(T1, T2)>>>>
boost::optional< V > Lookup(const KV &key, const Cont< Pair< K, V >, Rest...> &cont)
static const size_t ArgsCount
Container< T > Concat(const Container< Container< T >> &containers)
auto ConcatMap(Cont &&c, F &&f) -> decltype(Concat(Map(std::forward< Cont >(c), std::forward< F >(f))))
void Append(Res &result, T &&val, decltype(result.push_back(std::forward< T >(val)))*=nullptr)
Container< T > Filter(const Container< T > &c, F f)
constexpr bool IsSimpleContainer()
constexpr bool DoesReturnVoid()
auto Invoke(F &&f, Args &&...args) -> decltype(std::forward< F >(f)(std::forward< Args >(args)...))
typename WrapType< T >::type WrapType_t
constexpr bool IsInvokableWithConst()
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)