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