LeechCraft 0.6.70-14794-g33744ae6ce
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
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
17namespace boost
18{
19 template<typename>
21}
22
23namespace LC
24{
25namespace 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, decltype (result.push_back (std::forward<T> (val)))* = nullptr)
71 {
72 result.push_back (std::forward<T> (val));
73 }
74
75 template<typename Res, typename T>
76 void Append (Res& result, T&& val, decltype (result.insert (std::forward<T> (val)))* = nullptr)
77 {
78 result.insert (std::forward<T> (val));
79 }
80
81 template<typename>
82 struct CountArgs
83 {
84 static const size_t ArgsCount = 0;
85 };
86
87 template<template<typename...> class Container, typename... Args>
88 struct CountArgs<Container<Args...>>
89 {
90 static const size_t ArgsCount = sizeof... (Args);
91 };
92
93 template<typename C>
94 constexpr bool IsSimpleContainer ()
95 {
96 return CountArgs<std::decay_t<C>>::ArgsCount == 1;
97 }
98
99 template<typename Container, typename T>
100 struct Replace
101 {
102 using Type = struct Fail;
103 };
104
105 template<template<typename> class Container, typename U, typename T>
106 struct Replace<Container<U>, T>
107 {
108 using Type = Container<T>;
109 };
110
111 template<typename>
112 struct IsNotBrokenSFINAE : std::false_type {};
113
114 template<typename T>
115 struct IsNotBrokenSFINAE<boost::iterator_range<T>> : std::true_type {};
116
117 template<typename T>
119
120 template<template<typename...> class Fallback, bool ForceFallback, typename Container, typename F>
121 auto MapImpl (Container&& c, F f)
122 {
123 using FRet_t = std::decay_t<decltype (std::invoke (f, *c.begin ()))>;
124 static_assert (!std::is_same<void, FRet_t> {}, "The function shall not return void.");
125
126 using DecayContainer_t = std::decay_t<Container>;
127
128 using ResultCont_t = std::conditional_t<
129 !ForceFallback &&
130 detail::IsSimpleContainer<DecayContainer_t> () &&
131 !detail::IsNotBrokenSFINAE_v<DecayContainer_t>,
133 Fallback<FRet_t>>;
134
136 for (auto&& t : c)
137 Append (cont, std::invoke (f, t));
138 return cont;
139 }
140 }
141
142 template<typename Container, typename F>
143 auto Map (Container&& c, F f)
144 {
145 return detail::MapImpl<QList, false> (std::forward<Container> (c), std::forward<F> (f));
146 }
147
148 template<template<typename...> class Fallback, typename Container, typename F>
149 auto MapAs (Container&& c, F&& f)
150 {
151 return detail::MapImpl<Fallback, true> (std::forward<Container> (c), std::forward<F> (f));
152 }
153
154 template<typename T, template<typename U> class Container, typename F>
155 Container<T> Filter (const Container<T>& c, F f)
156 {
157 Container<T> result;
158 for (const auto& item : c)
159 if (std::invoke (f, item))
160 detail::Append (result, item);
161 return result;
162 }
163
164 template<template<typename> class Container, typename T>
165 Container<T> Concat (const Container<Container<T>>& containers)
166 {
167 Container<T> result;
168 for (const auto& cont : containers)
169 std::copy (cont.begin (), cont.end (), std::back_inserter (result));
170 return result;
171 }
172
173 template<template<typename...> class Container, typename... ContArgs>
174 auto Concat (const Container<ContArgs...>& containers) -> std::decay_t<decltype (*containers.begin ())>
175 {
176 std::decay_t<decltype (*containers.begin ())> result;
177 for (const auto& cont : containers)
178 for (const auto& item : cont)
179 detail::Append (result, item);
180 return result;
181 }
182
183 template<typename Cont, typename F>
184 auto ConcatMap (Cont&& c, F&& f)
185 {
186 return Concat (Map (std::forward<Cont> (c), std::forward<F> (f)));
187 }
188
189 template<template<typename> class Container, typename T>
190 Container<Container<T>> SplitInto (size_t numChunks, const Container<T>& container)
191 {
192 Container<Container<T>> result;
193
194 const size_t chunkSize = container.size () / numChunks;
195 for (size_t i = 0; i < numChunks; ++i)
196 {
197 Container<T> subcont;
198 const auto start = container.begin () + chunkSize * i;
199 const auto end = start + chunkSize;
200 std::copy (start, end, std::back_inserter (subcont));
201 result.push_back (subcont);
202 }
203
204 const auto lastStart = container.begin () + chunkSize * numChunks;
205 const auto lastEnd = container.end ();
206 std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
207
208 return result;
209 }
210
211 template<typename Cont>
212 decltype (auto) Sorted (Cont&& cont)
213 {
214 std::sort (cont.begin (), cont.end ());
215 return std::forward<Cont> (cont);
216 }
217
218 constexpr auto Id = [] (auto&& t) -> decltype (auto) { return std::forward<decltype (t)> (t); };
219
220 template<typename R>
221 auto ComparingBy (R r)
222 {
223 return [r] (const auto& left, const auto& right) { return std::invoke (r, left) < std::invoke (r, right); };
224 }
225
226 template<typename R>
227 auto EqualityBy (R r)
228 {
229 return [r] (const auto& left, const auto& right) { return std::invoke (r, left) == std::invoke (r, right); };
230 }
231
232 constexpr auto Apply = [] (const auto& t) { return t (); };
233
234 constexpr auto Fst = [] (const auto& pair) { return pair.first; };
235
236 constexpr auto Snd = [] (const auto& pair) { return pair.second; };
237
238 template<typename F>
239 auto First (F&& f)
240 {
241 return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.first); };
242 }
243
244 template<typename F>
245 auto Second (F&& f)
246 {
247 return [f = std::forward<F> (f)] (const auto& pair) { return std::invoke (f, pair.second); };
248 }
249}
250}
auto MapImpl(Container &&c, F f)
Definition: prelude.h:121
constexpr bool IsSimpleContainer()
Definition: prelude.h:94
constexpr bool IsNotBrokenSFINAE_v
Definition: prelude.h:118
void Append(Res &result, T &&val, decltype(result.push_back(std::forward< T >(val))) *=nullptr)
Definition: prelude.h:70
auto EqualityBy(R r)
Definition: prelude.h:227
Container< T > Filter(const Container< T > &c, F f)
Definition: prelude.h:155
auto First(F &&f)
Definition: prelude.h:239
auto ConcatMap(Cont &&c, F &&f)
Definition: prelude.h:184
typename WrapType< T >::type WrapType_t
Definition: prelude.h:34
Container< T > Concat(const Container< Container< T > > &containers)
Definition: prelude.h:165
auto MapAs(Container &&c, F &&f)
Definition: prelude.h:149
constexpr auto Id
Definition: prelude.h:218
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
decltype(auto) Sorted(Cont &&cont)
Definition: prelude.h:212
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 > >
Definition: prelude.h:60
constexpr auto Snd
Definition: prelude.h:236
auto ComparingBy(R r)
Definition: prelude.h:221
auto Map(Container &&c, F f)
Definition: prelude.h:143
constexpr auto Apply
Definition: prelude.h:232
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)
Definition: prelude.h:190
auto Second(F &&f)
Definition: prelude.h:245
constexpr auto Fst
Definition: prelude.h:234
Definition: constants.h:15
Definition: prelude.h:18
static const size_t ArgsCount
Definition: prelude.h:84