LeechCraft  0.6.70-10870-g558588d6ec
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 <functional>
33 #include <type_traits>
34 #include <iterator>
35 #include <QPair>
36 #include <QStringList>
37 #include <boost/optional.hpp>
38 
39 namespace boost
40 {
41  template<typename>
43 }
44 
45 namespace LeechCraft
46 {
47 namespace Util
48 {
49  template<typename T>
50  struct WrapType
51  {
52  using type = T;
53  };
54 
55  template<typename T>
56  using WrapType_t = typename WrapType<T>::type;
57 
58  template<>
59  struct WrapType<QList<QString>>
60  {
61  using type = QStringList;
62  };
63 
64  template<typename T1, typename T2, template<typename U> class Container, typename F>
65  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)>>>>
66  {
68 
69  using std::begin;
70  using std::end;
71 
72  auto i1 = begin (c1), e1 = end (c1);
73  auto i2 = begin (c2), e2 = end (c2);
74  for ( ; i1 != e1 && i2 != e2; ++i1, ++i2)
75  result.push_back (f (*i1, *i2));
76  return result;
77  }
78 
79  template<typename T1, typename T2,
80  template<typename U> class Container,
81  template<typename U1, typename U2> class Pair = QPair>
82  auto Zip (const Container<T1>& c1, const Container<T2>& c2) -> Container<Pair<T1, T2>>
83  {
84  return ZipWith (c1, c2,
85  [] (const T1& t1, const T2& t2) -> Pair<T1, T2>
86  { return { t1, t2}; });
87  }
88 
89  namespace detail
90  {
91  template<typename Res, typename T>
92  void Append (Res& result, T&& val, decltype (result.push_back (std::forward<T> (val)))* = nullptr)
93  {
94  result.push_back (std::forward<T> (val));
95  }
96 
97  template<typename Res, typename T>
98  void Append (Res& result, T&& val, decltype (result.insert (std::forward<T> (val)))* = nullptr)
99  {
100  result.insert (std::forward<T> (val));
101  }
102 
103  template<typename>
104  struct CountArgs
105  {
106  static const size_t ArgsCount = 0;
107  };
108 
109  template<template<typename...> class Container, typename... Args>
110  struct CountArgs<Container<Args...>>
111  {
112  static const size_t ArgsCount = sizeof... (Args);
113  };
114 
115  template<typename C>
116  constexpr bool IsSimpleContainer ()
117  {
118  return CountArgs<std::decay_t<C>>::ArgsCount == 1;
119  }
120 
121  template<typename Container, typename T>
122  struct Replace
123  {
124  using Type = struct Fail;
125  };
126 
127  template<template<typename> class Container, typename U, typename T>
128  struct Replace<Container<U>, T>
129  {
130  using Type = Container<T>;
131  };
132 
133  template<typename>
134  struct IsNotBrokenSFINAE : std::false_type {};
135 
136  template<typename T>
137  struct IsNotBrokenSFINAE<boost::iterator_range<T>> : std::true_type {};
138 
139  template<typename T>
141 
142  template<template<typename...> class Fallback, bool ForceFallback, typename Container, typename F>
143  auto MapImpl (Container&& c, F f)
144  {
145  using FRet_t = std::decay_t<decltype (std::invoke (f, *c.begin ()))>;
146  static_assert (!std::is_same<void, FRet_t> {}, "The function shall not return void.");
147 
148  using DecayContainer_t = std::decay_t<Container>;
149 
150  using ResultCont_t = std::conditional_t<
151  !ForceFallback &&
152  detail::IsSimpleContainer<DecayContainer_t> () &&
153  !detail::IsNotBrokenSFINAE_v<DecayContainer_t>,
155  Fallback<FRet_t>>;
156 
158  for (auto&& t : c)
159  detail::Append (cont, std::invoke (f, t));
160  return cont;
161  }
162  }
163 
164  template<typename Container, typename F>
165  auto Map (Container&& c, F f)
166  {
167  return detail::MapImpl<QList, false> (std::forward<Container> (c), std::forward<F> (f));
168  }
169 
170  template<template<typename...> class Fallback, typename Container, typename F>
171  auto MapAs (Container&& c, F&& f)
172  {
173  return detail::MapImpl<Fallback, true> (std::forward<Container> (c), std::forward<F> (f));
174  }
175 
176  template<typename T, template<typename U> class Container, typename F>
177  Container<T> Filter (const Container<T>& c, F f)
178  {
179  Container<T> result;
180  for (const auto& item : c)
181  if (std::invoke (f, item))
182  detail::Append (result, item);
183  return result;
184  }
185 
186  template<template<typename> class Container, typename T>
187  Container<T> Concat (const Container<Container<T>>& containers)
188  {
189  Container<T> result;
190  for (const auto& cont : containers)
191  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
192  return result;
193  }
194 
195  template<template<typename...> class Container, typename... ContArgs>
196  auto Concat (const Container<ContArgs...>& containers) -> std::decay_t<decltype (*containers.begin ())>
197  {
198  std::decay_t<decltype (*containers.begin ())> result;
199  for (const auto& cont : containers)
200  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
201  return result;
202  }
203 
204  template<typename Cont, typename F>
205  auto ConcatMap (Cont&& c, F&& f)
206  {
207  return Concat (Map (std::forward<Cont> (c), std::forward<F> (f)));
208  }
209 
210  template<template<typename> class Container, typename T>
211  Container<Container<T>> SplitInto (size_t numChunks, const Container<T>& container)
212  {
213  Container<Container<T>> result;
214 
215  const size_t chunkSize = container.size () / numChunks;
216  for (size_t i = 0; i < numChunks; ++i)
217  {
218  Container<T> subcont;
219  const auto start = container.begin () + chunkSize * i;
220  const auto end = start + chunkSize;
221  std::copy (start, end, std::back_inserter (subcont));
222  result.push_back (subcont);
223  }
224 
225  const auto lastStart = container.begin () + chunkSize * numChunks;
226  const auto lastEnd = container.end ();
227  std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
228 
229  return result;
230  }
231 
232  template<template<typename Pair, typename... Rest> class Cont, template<typename K, typename V> class Pair, typename K, typename V, typename KV, typename... Rest>
233  boost::optional<V> Lookup (const KV& key, const Cont<Pair<K, V>, Rest...>& cont)
234  {
235  for (const auto& pair : cont)
236  if (pair.first == key)
237  return pair.second;
238 
239  return {};
240  }
241 
242  template<typename Cont>
243  Cont Sorted (Cont&& cont)
244  {
245  std::sort (cont.begin (), cont.end ());
246  return cont;
247  }
248 
249  const auto Id = [] (const auto& t) { return t; };
250 
251  template<typename R>
252  auto ComparingBy (R r)
253  {
254  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) < std::invoke (r, right); };
255  }
256 
257  template<typename R>
258  auto EqualityBy (R r)
259  {
260  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) == std::invoke (r, right); };
261  }
262 
263  const auto Apply = [] (const auto& t) { return t (); };
264 
265  const auto Fst = [] (const auto& pair) { return pair.first; };
266 
267  const auto Snd = [] (const auto& pair) { return pair.second; };
268 
269  template<typename F>
270  auto First (F&& f)
271  {
272  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.first); };
273  }
274 
275  template<typename F>
276  auto Second (F&& f)
277  {
278  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.second); };
279  }
280 
281  template<typename F>
282  auto Flip (F&& f)
283  {
284  return [f = std::move (f)] (auto&& left, auto&& right)
285  {
286  return f (std::forward<decltype (right)> (right),
287  std::forward<decltype (left)> (left));
288  };
289  }
290 }
291 }
auto First(F &&f)
Definition: prelude.h:270
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:931
const auto Id
Definition: prelude.h:249
Definition: prelude.h:39
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 >>
Definition: prelude.h:82
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)>>>>
Definition: prelude.h:65
auto ComparingBy(R r)
Definition: prelude.h:252
constexpr bool IsNotBrokenSFINAE_v
Definition: prelude.h:140
const auto Snd
Definition: prelude.h:267
static const size_t ArgsCount
Definition: prelude.h:106
Container< T > Concat(const Container< Container< T >> &containers)
Definition: prelude.h:187
void Append(Res &result, T &&val, decltype(result.push_back(std::forward< T >(val))) *=nullptr)
Definition: prelude.h:92
auto Flip(F &&f)
Definition: prelude.h:282
const auto Apply
Definition: prelude.h:263
auto ConcatMap(Cont &&c, F &&f)
Definition: prelude.h:205
Container< T > Filter(const Container< T > &c, F f)
Definition: prelude.h:177
constexpr bool IsSimpleContainer()
Definition: prelude.h:116
auto Map(Container &&c, F f)
Definition: prelude.h:165
Cont Sorted(Cont &&cont)
Definition: prelude.h:243
auto Second(F &&f)
Definition: prelude.h:276
const auto Fst
Definition: prelude.h:265
auto MapImpl(Container &&c, F f)
Definition: prelude.h:143
auto MapAs(Container &&c, F &&f)
Definition: prelude.h:171
auto EqualityBy(R r)
Definition: prelude.h:258
boost::optional< V > Lookup(const KV &key, const Cont< Pair< K, V >, Rest... > &cont)
Definition: prelude.h:233
typename WrapType< T >::type WrapType_t
Definition: prelude.h:56
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)
Definition: prelude.h:211