LeechCraft  0.6.70-15082-g543737046d
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  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <functional>
12 #include <type_traits>
13 #include <iterator>
14 #include <QPair>
15 #include <QStringList>
16 
17 namespace boost
18 {
19  template<typename>
20  class iterator_range;
21 }
22 
23 namespace LC
24 {
25 namespace Util
26 {
27  template<typename T>
28  struct WrapType
29  {
30  using type = T;
31  };
32 
33  template<typename T>
34  using WrapType_t = typename WrapType<T>::type;
35 
36  template<>
37  struct WrapType<QList<QString>>
38  {
39  using type = QStringList;
40  };
41 
42  template<template<typename U> class Container, typename T1, typename T2, typename F>
43  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)>>>>
44  {
45  WrapType_t<Container<std::decay_t<std::result_of_t<F (T1, T2)>>>> result;
46 
47  using std::begin;
48  using std::end;
49 
50  auto i1 = begin (c1), e1 = end (c1);
51  auto i2 = begin (c2), e2 = end (c2);
52  for ( ; i1 != e1 && i2 != e2; ++i1, ++i2)
53  result.push_back (f (*i1, *i2));
54  return result;
55  }
56 
57  template<typename T1, typename T2,
58  template<typename U> class Container,
59  template<typename U1, typename U2> class Pair = QPair>
60  auto Zip (const Container<T1>& c1, const Container<T2>& c2) -> Container<Pair<T1, T2>>
61  {
62  return ZipWith (c1, c2,
63  [] (const T1& t1, const T2& t2) -> Pair<T1, T2>
64  { return { t1, t2}; });
65  }
66 
67  namespace detail
68  {
69  template<typename Res, typename T>
70  void Append (Res& result, T&& val) noexcept
71  {
72  if constexpr (requires { result.push_back (std::forward<T> (val)); })
73  result.push_back (std::forward<T> (val));
74  else
75  result.insert (std::forward<T> (val));
76  }
77 
78  template<typename>
79  struct CountArgs
80  {
81  static const size_t ArgsCount = 0;
82  };
83 
84  template<template<typename...> class Container, typename... Args>
85  struct CountArgs<Container<Args...>>
86  {
87  static const size_t ArgsCount = sizeof... (Args);
88  };
89 
90  template<typename C>
91  constexpr bool IsSimpleContainer ()
92  {
93  return CountArgs<std::decay_t<C>>::ArgsCount == 1;
94  }
95 
96  template<typename Container, typename T>
97  struct Replace
98  {
99  using Type = struct Fail;
100  };
101 
102  template<template<typename> class Container, typename U, typename T>
103  struct Replace<Container<U>, T>
104  {
105  using Type = Container<T>;
106  };
107 
108  template<typename>
109  struct IsNotBrokenSFINAE : std::false_type {};
110 
111  template<typename T>
112  struct IsNotBrokenSFINAE<boost::iterator_range<T>> : std::true_type {};
113 
114  template<typename T>
116 
117  template<template<typename...> class Fallback, bool ForceFallback, typename Container, typename F>
118  auto MapImpl (Container&& c, F f)
119  {
120  using FRet_t = std::decay_t<decltype (std::invoke (f, *c.begin ()))>;
121  static_assert (!std::is_same<void, FRet_t> {}, "The function shall not return void.");
122 
123  using DecayContainer_t = std::decay_t<Container>;
124 
125  using ResultCont_t = std::conditional_t<
126  !ForceFallback &&
127  detail::IsSimpleContainer<DecayContainer_t> () &&
128  !detail::IsNotBrokenSFINAE_v<DecayContainer_t>,
130  Fallback<FRet_t>>;
131 
133  for (auto&& t : c)
134  Append (cont, std::invoke (f, t));
135  return cont;
136  }
137  }
138 
139  // NOTE
140  // The noexcept specifier here is somewhat misleading:
141  // this function indeed _might_ throw if the underlying container throws
142  // when appending an element, for any reason,
143  // (be it a copy/move ctor throwing or failure to allocate memory).
144  // Due to how LC is written and intended to be used,
145  // such exceptions are not and should not be handled,
146  // so they are fatal anyway.
147  // Thus we're totally fine with std::unexpected() and the likes.
148  template<typename Container, typename F>
149  auto Map (Container&& c, F&& f) noexcept (noexcept (std::is_nothrow_invocable_v<F, decltype (*c.begin ())>))
150  {
151  return detail::MapImpl<QList, false> (std::forward<Container> (c), std::forward<F> (f));
152  }
153 
154  template<template<typename...> class Fallback, typename Container, typename F>
155  auto MapAs (Container&& c, F&& f) noexcept (noexcept (std::is_nothrow_invocable_v<F, decltype (*c.begin ())>))
156  {
157  return detail::MapImpl<Fallback, true> (std::forward<Container> (c), std::forward<F> (f));
158  }
159 
160  template<typename T, template<typename U> class Container, typename F>
161  Container<T> Filter (const Container<T>& c, F f)
162  {
163  Container<T> result;
164  for (const auto& item : c)
165  if (std::invoke (f, item))
166  detail::Append (result, item);
167  return result;
168  }
169 
170  template<template<typename> class Container, typename T>
171  Container<T> Concat (const Container<Container<T>>& containers)
172  {
173  Container<T> result;
174  for (const auto& cont : containers)
175  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
176  return result;
177  }
178 
179  template<template<typename...> class Container, typename... ContArgs>
180  auto Concat (const Container<ContArgs...>& containers) -> std::decay_t<decltype (*containers.begin ())>
181  {
182  std::decay_t<decltype (*containers.begin ())> result;
183  for (const auto& cont : containers)
184  for (const auto& item : cont)
185  detail::Append (result, item);
186  return result;
187  }
188 
189  template<typename Cont, typename F>
190  auto ConcatMap (Cont&& c, F&& f)
191  {
192  return Concat (Map (std::forward<Cont> (c), std::forward<F> (f)));
193  }
194 
195  template<template<typename> class Container, typename T>
196  Container<Container<T>> SplitInto (size_t numChunks, const Container<T>& container)
197  {
198  Container<Container<T>> result;
199 
200  const size_t chunkSize = container.size () / numChunks;
201  for (size_t i = 0; i < numChunks; ++i)
202  {
203  Container<T> subcont;
204  const auto start = container.begin () + chunkSize * i;
205  const auto end = start + chunkSize;
206  std::copy (start, end, std::back_inserter (subcont));
207  result.push_back (subcont);
208  }
209 
210  const auto lastStart = container.begin () + chunkSize * numChunks;
211  const auto lastEnd = container.end ();
212  std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
213 
214  return result;
215  }
216 
217  template<typename Cont>
218  decltype (auto) Sorted (Cont&& cont)
219  {
220  std::sort (cont.begin (), cont.end ());
221  return std::forward<Cont> (cont);
222  }
223 
224  constexpr auto Id = [] (auto&& t) -> decltype (auto) { return std::forward<decltype (t)> (t); };
225 
226  template<typename R>
227  auto ComparingBy (R r)
228  {
229  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) < std::invoke (r, right); };
230  }
231 
232  template<typename R>
233  auto EqualityBy (R r)
234  {
235  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) == std::invoke (r, right); };
236  }
237 
238  constexpr auto Apply = [] (const auto& t) { return t (); };
239 
240  constexpr auto Fst = [] (const auto& pair) { return pair.first; };
241 
242  constexpr auto Snd = [] (const auto& pair) { return pair.second; };
243 
244  template<typename F>
245  auto First (F&& f)
246  {
247  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.first); };
248  }
249 
250  template<typename F>
251  auto Second (F&& f)
252  {
253  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.second); };
254  }
255 }
256 }
LC::Util::Apply
constexpr auto Apply
Definition: prelude.h:238
LC::Util::Concat
Container< T > Concat(const Container< Container< T >> &containers)
Definition: prelude.h:171
LC::Util::WrapType< QList< QString > >::type
QStringList type
Definition: prelude.h:39
LC::Util::ComparingBy
auto ComparingBy(R r)
Definition: prelude.h:227
QList
Definition: ianrulesstorage.h:14
LC::Util::WrapType
Definition: prelude.h:28
LC::Util::detail::Replace::Type
struct Fail Type
Definition: prelude.h:99
boost
Definition: prelude.h:17
LC::Util::detail::IsSimpleContainer
constexpr bool IsSimpleContainer()
Definition: prelude.h:91
LC::Util::MapAs
auto MapAs(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
Definition: prelude.h:155
LC::Util::Second
auto Second(F &&f)
Definition: prelude.h:251
LC::Util::detail::Replace< Container< U >, T >::Type
Container< T > Type
Definition: prelude.h:105
LC::Util::detail::IsNotBrokenSFINAE_v
constexpr bool IsNotBrokenSFINAE_v
Definition: prelude.h:115
LC::Util::Map
auto Map(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
Definition: prelude.h:149
LC::Util::SplitInto
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)
Definition: prelude.h:196
LC::Util::First
auto First(F &&f)
Definition: prelude.h:245
LC::Util::Filter
Container< T > Filter(const Container< T > &c, F f)
Definition: prelude.h:161
LC::Util::Sorted
decltype(auto) Sorted(Cont &&cont)
Definition: prelude.h:218
LC::Util::Id
constexpr auto Id
Definition: prelude.h:224
LC::Util::detail::CountArgs::ArgsCount
static const size_t ArgsCount
Definition: prelude.h:81
LC::Util::EqualityBy
auto EqualityBy(R r)
Definition: prelude.h:233
LC::Util::Fst
constexpr auto Fst
Definition: prelude.h:240
LC::Util::detail::IsNotBrokenSFINAE
Definition: prelude.h:109
LC
Definition: constants.h:14
boost::iterator_range
Definition: prelude.h:26
LC::Util::detail::MapImpl
auto MapImpl(Container &&c, F f)
Definition: prelude.h:118
LC::Util::oral::sph::f
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:952
LC::Util::ZipWith
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:43
LC::Util::detail::CountArgs
Definition: prelude.h:79
LC::Util::Snd
constexpr auto Snd
Definition: prelude.h:242
LC::Util::ConcatMap
auto ConcatMap(Cont &&c, F &&f)
Definition: prelude.h:190
LC::Util::WrapType_t
typename WrapType< T >::type WrapType_t
Definition: prelude.h:34
LC::Util::WrapType::type
T type
Definition: prelude.h:30
LC::Util::Zip
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 >>
Definition: prelude.h:60
LC::Util::detail::Append
void Append(Res &result, T &&val) noexcept
Definition: prelude.h:70
LC::Util::detail::Replace
Definition: prelude.h:97