LeechCraft  0.6.70-6645-gcd10d7e
Modular cross-platform feature rich live environment.
prelude.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #pragma once
31 
32 #include <type_traits>
33 #include <iterator>
34 #include <QPair>
35 #include <QStringList>
36 #include <boost/optional.hpp>
37 #include "oldcppkludges.h"
38 
39 namespace LeechCraft
40 {
41 namespace Util
42 {
43  template<typename T>
44  struct WrapType
45  {
46  using type = T;
47  };
48 
49  template<typename T>
50  using WrapType_t = typename WrapType<T>::type;
51 
52  template<>
53  struct WrapType<QList<QString>>
54  {
55  using type = QStringList;
56  };
57 
58  template<typename T1, typename T2, template<typename U> class Container, typename F>
59  auto ZipWith (const Container<T1>& c1, const Container<T2>& c2, F f) -> WrapType_t<Container<Decay_t<ResultOf_t<F (T1, T2)>>>>
60  {
62 
63  using std::begin;
64  using std::end;
65 
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));
70  return result;
71  }
72 
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>>
77  {
78  return ZipWith (c1, c2,
79  [] (const T1& t1, const T2& t2) -> Pair<T1, T2>
80  { return { t1, t2}; });
81  }
82 
83  namespace detail
84  {
85  template<typename Res, typename T>
86  void Append (Res& result, T&& val, decltype (result.push_back (std::forward<T> (val)))* = nullptr)
87  {
88  result.push_back (std::forward<T> (val));
89  }
90 
91  template<typename Res, typename T>
92  void Append (Res& result, T&& val, decltype (result.insert (std::forward<T> (val)))* = nullptr)
93  {
94  result.insert (std::forward<T> (val));
95  }
96 
97  template<typename T, typename F>
98  constexpr bool IsInvokableWithConstImpl (typename std::result_of<F (const T&)>::type*)
99  {
100  return true;
101  }
102 
103  template<typename T, typename F>
104  constexpr bool IsInvokableWithConstImpl (...)
105  {
106  return false;
107  }
108 
109  template<typename T, typename F>
110  constexpr bool IsInvokableWithConst ()
111  {
112  return IsInvokableWithConstImpl<typename std::decay<T>::type, F> (0);
113  }
114 
115  template<template<typename> class Cont, typename T>
116  constexpr bool IsSimpleContainer ()
117  {
118  return true;
119  }
120 
121  template<typename C>
122  constexpr bool IsSimpleContainer ()
123  {
124  return false;
125  }
126  }
127 
128  template<typename T, template<typename U> class Container, typename F>
129  auto Map (const Container<T>& c, F f) -> typename std::enable_if<!std::is_same<void, decltype (Invoke (f, *c.begin ()))>::value,
130  WrapType_t<Container<typename std::decay<decltype (Invoke (f, *c.begin ()))>::type>>>::type
131  {
132  Container<typename std::decay<decltype (Invoke (f, *c.begin ()))>::type> result;
133  for (auto&& t : c)
134  detail::Append (result, Invoke (f, t));
135  return result;
136  }
137 
138  template<typename Container, typename F, template<typename> class ResultCont = QList>
139  auto Map (const Container& c, F f) -> typename std::enable_if<!detail::IsSimpleContainer<Container> () && !std::is_same<void, decltype (Invoke (f, *c.begin ()))>::value,
140  WrapType_t<ResultCont<typename std::decay<decltype (Invoke (f, *c.begin ()))>::type>>>::type
141  {
142  ResultCont<typename std::decay<decltype (Invoke (f, *c.begin ()))>::type> cont;
143  for (auto&& t : c)
144  detail::Append (cont, Invoke (f, t));
145  return cont;
146  }
147 
148  template<typename Container, typename F>
149  auto Map (Container& c, F f) -> typename std::enable_if<!detail::IsSimpleContainer<Container> () && std::is_same<void, decltype (Invoke (f, *c.begin ()))>::value>::type
150  {
151  for (auto&& t : c)
152  Invoke (f, t);
153  }
154 
155  template<typename Container, typename F, typename... ContArgs>
156  auto Map (const Container& c, F f) -> typename std::enable_if<!detail::IsSimpleContainer<Container> () && std::is_same<void, decltype (Invoke (f, *c.begin ()))>::value>::type
157  {
158  auto copy = c;
159  Map (copy, f);
160  }
161 
162  /*
163 #ifndef USE_CPP14
164  template<typename F>
165  auto Map (const QStringList& c, F f) -> typename std::enable_if<!std::is_same<void, decltype (Invoke (f, QString {}))>::value,
166  WrapType_t<QList<typename std::decay<decltype (Invoke (f, QString {}))>::type>>>::type
167  {
168  WrapType_t<QList<typename std::decay<decltype (Invoke (f, QString {}))>::type>> result;
169  for (auto&& t : c)
170  result.push_back (Invoke (f, t));
171  return result;
172  }
173 
174  template<typename F>
175  auto Map (const QStringList& c, F f) -> typename std::enable_if<std::is_same<void, decltype (Invoke (f, QString {}))>::value>::type
176  {
177  for (auto&& t : c)
178  Invoke (f, t);
179  }
180 #endif
181 */
182 
183  template<typename T, template<typename U> class Container, typename F>
184  auto Map (const Container<T>& c, F f) -> typename std::enable_if<std::is_same<void, decltype (Invoke (f, std::declval<T> ()))>::value, void>::type
185  {
186  for (auto&& t : c)
187  Invoke (f, t);
188  }
189 
190  template<typename T, template<typename U> class Container, typename F>
191  Container<T> Filter (const Container<T>& c, F f)
192  {
193  Container<T> result;
194  for (const auto& item : c)
195  if (Invoke (f, item))
196  result.push_back (item);
197  return result;
198  }
199 
200  template<template<typename> class Container, typename T>
201  Container<T> Concat (const Container<Container<T>>& containers)
202  {
203  Container<T> result;
204  for (const auto& cont : containers)
205  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
206  return result;
207  }
208 
209  template<template<typename...> class Container, typename... ContArgs>
210  auto Concat (const Container<ContArgs...>& containers) -> typename std::decay<decltype (*containers.begin ())>::type
211  {
212  typename std::decay<decltype (*containers.begin ())>::type result;
213  for (const auto& cont : containers)
214  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
215  return result;
216  }
217 
218  template<typename Cont, typename F>
219  auto ConcatMap (Cont&& c, F&& f) -> decltype (Concat (Map (std::forward<Cont> (c), std::forward<F> (f))))
220  {
221  return Concat (Map (std::forward<Cont> (c), std::forward<F> (f)));
222  }
223 
224  template<template<typename> class Container, typename T>
225  Container<Container<T>> SplitInto (size_t numChunks, const Container<T>& container)
226  {
227  Container<Container<T>> result;
228 
229  const size_t chunkSize = container.size () / numChunks;
230  for (size_t i = 0; i < numChunks; ++i)
231  {
232  Container<T> subcont;
233  const auto start = container.begin () + chunkSize * i;
234  const auto end = start + chunkSize;
235  std::copy (start, end, std::back_inserter (subcont));
236  result.push_back (subcont);
237  }
238 
239  const auto lastStart = container.begin () + chunkSize * numChunks;
240  const auto lastEnd = container.end ();
241  std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
242 
243  return result;
244  }
245 
246  template<template<typename Pair, typename... Rest> class Cont, template<typename K, typename V> class Pair, typename K, typename V, typename KV, typename... Rest>
247  boost::optional<V> Lookup (const KV& key, const Cont<Pair<K, V>, Rest...>& cont)
248  {
249  for (const auto& pair : cont)
250  if (pair.first == key)
251  return pair.second;
252 
253  return {};
254  }
255 
256  template<typename Cont>
257  Cont Sorted (Cont&& cont)
258  {
259  std::sort (cont.begin (), cont.end ());
260  return cont;
261  }
262 
263 #ifdef USE_CPP14
264  template<typename R>
265  auto ComparingBy (R r)
266  {
267  return [r] (const auto& left, const auto& right) { return Invoke (r, left) < Invoke (r, right); };
268  }
269 
270  const auto Apply = [] (const auto& t) { return t (); };
271 
272  template<typename F>
273  auto First (F&& f)
274  {
275  return [f = std::move (f)] (const auto& pair) { return Invoke (f, pair.first); };
276  }
277 
278  template<typename F>
279  auto Second (F&& f)
280  {
281  return [f = std::move (f)] (const auto& pair) { return Invoke (f, pair.second); };
282  }
283 #else
284  namespace detail
285  {
286  template<typename R>
288  {
289  const R R_;
290 
291  template<typename T>
292  bool operator() (const T& left, const T& right) const
293  {
294  return Invoke (R_, left) < Invoke (R_, right);
295  }
296  };
297  }
298 
299  template<typename R>
301  {
302  return detail::ComparingByClosure<R> { r };
303  }
304 
305  struct
306  {
307  template<typename T>
308  typename std::result_of<T ()>::type operator() (const T& t) const
309  {
310  return t ();
311  }
312  } const Apply {};
313 
314  namespace detail
315  {
316  template<typename F>
317  struct Fst
318  {
319  F F_;
320 
321  template<typename Pair>
322  auto operator() (const Pair& pair) -> decltype (Invoke (F_, pair.first))
323  {
324  return Invoke (F_, pair.first);
325  }
326  };
327 
328  template<typename F>
329  struct Snd
330  {
331  F F_;
332 
333  template<typename Pair>
334  auto operator() (const Pair& pair) -> decltype (Invoke (F_, pair.second))
335  {
336  return Invoke (F_, pair.second);
337  }
338  };
339  }
340 
341  template<typename F>
343  {
344  return { f };
345  }
346 
347  template<typename F>
349  {
350  return { f };
351  }
352 #endif
353 }
354 }
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 >>
Definition: prelude.h:76
constexpr bool IsInvokableWithConstImpl(...)
Definition: prelude.h:104
auto ZipWith(const Container< T1 > &c1, const Container< T2 > &c2, F f) -> WrapType_t< Container< Decay_t< ResultOf_t< F(T1, T2)>>>>
Definition: prelude.h:59
Container< T > Concat(const Container< Container< T >> &containers)
Definition: prelude.h:201
struct LeechCraft::Util::@2 Apply
detail::ComparingByClosure< R > ComparingBy(R r)
Definition: prelude.h:300
auto ConcatMap(Cont &&c, F &&f) -> decltype(Concat(Map(std::forward< Cont >(c), std::forward< F >(f))))
Definition: prelude.h:219
detail::Snd< F > Second(F f)
Definition: prelude.h:348
void Append(Res &result, T &&val, decltype(result.insert(std::forward< T >(val)))*=nullptr)
Definition: prelude.h:92
void Append(Res &result, T &&val, decltype(result.push_back(std::forward< T >(val)))*=nullptr)
Definition: prelude.h:86
Container< T > Filter(const Container< T > &c, F f)
Definition: prelude.h:191
constexpr bool IsSimpleContainer()
Definition: prelude.h:122
auto Map(const Container< T > &c, F f) -> typename std::enable_if<!std::is_same< void, decltype(Invoke(f,*c.begin()))>::value, WrapType_t< Container< typename std::decay< decltype(Invoke(f,*c.begin()))>::type >>>::type
Definition: prelude.h:129
Cont Sorted(Cont &&cont)
Definition: prelude.h:257
detail::Fst< F > First(F f)
Definition: prelude.h:342
auto Invoke(F &&f, Args &&...args) -> decltype(std::forward< F >(f)(std::forward< Args >(args)...))
Definition: oldcppkludges.h:39
boost::optional< V > Lookup(const KV &key, const Cont< Pair< K, V >, Rest... > &cont)
Definition: prelude.h:247
typename WrapType< T >::type WrapType_t
Definition: prelude.h:50
constexpr bool IsInvokableWithConst()
Definition: prelude.h:110
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)
Definition: prelude.h:225