LeechCraft  0.6.70-16373-g319c272718
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 LC
18 {
19 namespace Util
20 {
21  template<typename T>
22  struct WrapType
23  {
24  using type = T;
25  };
26 
27  template<typename T>
28  using WrapType_t = typename WrapType<T>::type;
29 
30  template<>
31  struct WrapType<QList<QString>>
32  {
33  using type = QStringList;
34  };
35 
36  template<template<typename U> class Container, typename T1, typename T2, typename F>
37  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)>>>>
38  {
40 
41  using std::begin;
42  using std::end;
43 
44  auto i1 = begin (c1), e1 = end (c1);
45  auto i2 = begin (c2), e2 = end (c2);
46  for ( ; i1 != e1 && i2 != e2; ++i1, ++i2)
47  result.push_back (f (*i1, *i2));
48  return result;
49  }
50 
51  template<typename T1, typename T2,
52  template<typename U> class Container,
53  template<typename U1, typename U2> class Pair = QPair>
54  auto Zip (const Container<T1>& c1, const Container<T2>& c2) -> Container<Pair<T1, T2>>
55  {
56  return ZipWith (c1, c2,
57  [] (const T1& t1, const T2& t2) -> Pair<T1, T2>
58  { return { t1, t2}; });
59  }
60 
61  namespace detail
62  {
63  template<typename Res, typename T>
64  void Append (Res& result, T&& val) noexcept
65  {
66  if constexpr (requires { result.push_back (std::forward<T> (val)); })
67  result.push_back (std::forward<T> (val));
68  else
69  result.insert (std::forward<T> (val));
70  }
71 
72  template<typename Container, typename T>
73  struct Replace
74  {
75  using Type = QList<T>;
76  };
77 
78  template<template<typename...> class Container, typename U, typename T>
79  struct Replace<Container<U>, T>
80  {
81  using Type = Container<T>;
82  };
83 
84  template<typename ResultContainer, typename Container, typename F>
85  auto MapImpl (Container&& c, F f)
86  {
88  for (auto&& t : c)
89  Append (cont, std::invoke (f, t));
90  return cont;
91  }
92  }
93 
94  // NOTE
95  // The noexcept specifier here is somewhat misleading:
96  // this function indeed _might_ throw if the underlying container throws
97  // when appending an element, for any reason,
98  // (be it a copy/move ctor throwing or failure to allocate memory).
99  // Due to how LC is written and intended to be used,
100  // such exceptions are not and should not be handled,
101  // so they are fatal anyway.
102  // Thus we're totally fine with std::unexpected() and the likes.
103  template<typename Container, typename F>
104  auto Map (Container&& c, F&& f) noexcept (noexcept (std::is_nothrow_invocable_v<F, decltype (*c.begin ())>))
105  {
106  using FRet_t = std::decay_t<decltype (std::invoke (f, *c.begin ()))>;
107  return detail::MapImpl<typename detail::Replace<std::decay_t<Container>, FRet_t>::Type> (std::forward<Container> (c), std::forward<F> (f));
108  }
109 
110  template<template<typename...> class Fallback, typename Container, typename F>
111  auto MapAs (Container&& c, F&& f) noexcept (noexcept (std::is_nothrow_invocable_v<F, decltype (*c.begin ())>))
112  {
113  using FRet_t = std::decay_t<decltype (std::invoke (f, *c.begin ()))>;
114  return detail::MapImpl<Fallback<FRet_t>> (std::forward<Container> (c), std::forward<F> (f));
115  }
116 
117  template<typename T, template<typename U> class Container, typename F>
118  Container<T> Filter (const Container<T>& c, F f)
119  {
120  Container<T> result;
121  for (const auto& item : c)
122  if (std::invoke (f, item))
123  detail::Append (result, item);
124  return result;
125  }
126 
127  template<template<typename> class Container, typename T>
128  Container<T> Concat (const Container<Container<T>>& containers)
129  {
130  Container<T> result;
131 
132  decltype (result.size ()) size {};
133  for (const auto& cont : containers)
134  size += cont.size ();
135  result.reserve (size);
136 
137  for (const auto& cont : containers)
138  std::copy (cont.begin (), cont.end (), std::back_inserter (result));
139  return result;
140  }
141 
142  template<template<typename> class Container, typename T>
143  Container<T> Concat (Container<Container<T>>&& containers)
144  {
145  Container<T> result;
146 
147  decltype (result.size ()) size {};
148  for (const auto& cont : containers)
149  size += cont.size ();
150  result.reserve (size);
151 
152  for (auto&& cont : containers)
153  std::move (cont.begin (), cont.end (), std::back_inserter (result));
154  return result;
155  }
156 
157  template<template<typename...> class Container, typename... ContArgs>
158  auto Concat (const Container<ContArgs...>& containers) -> std::decay_t<decltype (*containers.begin ())>
159  {
160  std::decay_t<decltype (*containers.begin ())> result;
161  for (const auto& cont : containers)
162  for (const auto& item : cont)
163  detail::Append (result, item);
164  return result;
165  }
166 
167  template<typename Cont, typename F>
168  auto ConcatMap (Cont&& c, F&& f)
169  {
170  return Concat (Map (std::forward<Cont> (c), std::forward<F> (f)));
171  }
172 
173  template<template<typename> class Container, typename T>
174  Container<Container<T>> SplitInto (size_t numChunks, const Container<T>& container)
175  {
176  Container<Container<T>> result;
177 
178  const size_t chunkSize = container.size () / numChunks;
179  for (size_t i = 0; i < numChunks; ++i)
180  {
181  Container<T> subcont;
182  const auto start = container.begin () + chunkSize * i;
183  const auto end = start + chunkSize;
184  std::copy (start, end, std::back_inserter (subcont));
185  result.push_back (subcont);
186  }
187 
188  const auto lastStart = container.begin () + chunkSize * numChunks;
189  const auto lastEnd = container.end ();
190  std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
191 
192  return result;
193  }
194 
195  template<typename Cont>
196  decltype (auto) Sorted (Cont&& cont)
197  {
198  std::sort (cont.begin (), cont.end ());
199  return std::forward<Cont> (cont);
200  }
201 
202  constexpr auto Id = [] (auto&& t) -> decltype (auto) { return std::forward<decltype (t)> (t); };
203 
204  template<typename R>
205  auto ComparingBy (R r)
206  {
207  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) < std::invoke (r, right); };
208  }
209 
210  template<typename R>
211  auto EqualityBy (R r)
212  {
213  return [r] (const auto& left, const auto& right) { return std::invoke (r, left) == std::invoke (r, right); };
214  }
215 
216  constexpr auto Apply = [] (const auto& t) { return t (); };
217 
218  constexpr auto Fst = [] (const auto& pair) { return pair.first; };
219 
220  constexpr auto Snd = [] (const auto& pair) { return pair.second; };
221 
222  template<typename F>
223  auto First (F&& f)
224  {
225  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.first); };
226  }
227 
228  template<typename F>
229  auto Second (F&& f)
230  {
231  return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.second); };
232  }
233 }
234 }
Container< T > Concat(const Container< Container< T >> &containers)
Definition: prelude.h:128
constexpr auto Apply
Definition: prelude.h:216
auto ComparingBy(R r)
Definition: prelude.h:205
auto Second(F &&f)
Definition: prelude.h:229
auto MapAs(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
Definition: prelude.h:111
auto Map(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
Definition: prelude.h:104
Container< T > Filter(const Container< T > &c, F f)
Definition: prelude.h:118
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptr > > f
Definition: oral.h:951
Type
Describes the various types of XDG .desktop files.
Definition: itemtypes.h:23
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)
Definition: prelude.h:174
auto First(F &&f)
Definition: prelude.h:223
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
constexpr auto Id
Definition: prelude.h:202
decltype(auto) Sorted(Cont &&cont)
Definition: prelude.h:196
auto MapImpl(Container &&c, F f)
Definition: prelude.h:85
auto EqualityBy(R r)
Definition: prelude.h:211
constexpr auto Fst
Definition: prelude.h:218
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:41
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:37
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 >>
Definition: prelude.h:54
void Append(Res &result, T &&val) noexcept
Definition: prelude.h:64
auto ConcatMap(Cont &&c, F &&f)
Definition: prelude.h:168
constexpr auto Snd
Definition: prelude.h:220
typename WrapType< T >::type WrapType_t
Definition: prelude.h:28