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)>>>>
39 WrapType_t<Container<std::decay_t<std::result_of_t<F (T1, T2)>>>> result;
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));
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>>
57 [] (
const T1& t1,
const T2& t2) -> Pair<T1, T2>
58 {
return { t1, t2}; });
63 template<
typename Res,
typename T>
64 void Append (Res& result, T&& val)
noexcept
66 if constexpr (
requires { result.push_back (std::forward<T> (val)); })
67 result.push_back (std::forward<T> (val));
69 result.insert (std::forward<T> (val));
72 template<
typename Container,
typename T>
78 template<
template<
typename...>
class Container,
typename U,
typename T>
84 template<
typename ResultContainer,
typename Container,
typename F>
89 Append (cont, std::invoke (f, t));
103 template<
typename Container,
typename F>
104 auto Map (Container&& c, F&& f)
noexcept (
noexcept (std::is_nothrow_invocable_v<F,
decltype (*c.begin ())>))
106 using FRet_t = std::decay_t<
decltype (std::invoke (f, *c.begin ()))>;
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 ())>))
113 using FRet_t = std::decay_t<
decltype (std::invoke (f, *c.begin ()))>;
117 template<
typename T,
template<
typename U>
class Container,
typename F>
118 Container<T>
Filter (
const Container<T>& c, F f)
121 for (
const auto& item : c)
122 if (std::invoke (f, item))
127 template<
template<
typename>
class Container,
typename T>
128 Container<T>
Concat (
const Container<Container<T>>& containers)
132 decltype (result.size ()) size {};
133 for (
const auto& cont : containers)
134 size += cont.size ();
135 result.reserve (size);
137 for (
const auto& cont : containers)
138 std::copy (cont.begin (), cont.end (), std::back_inserter (result));
142 template<
template<
typename>
class Container,
typename T>
143 Container<T>
Concat (Container<Container<T>>&& containers)
147 decltype (result.size ()) size {};
148 for (
const auto& cont : containers)
149 size += cont.size ();
150 result.reserve (size);
152 for (
auto&& cont : containers)
153 std::move (cont.begin (), cont.end (), std::back_inserter (result));
157 template<
template<
typename...>
class Container,
typename... ContArgs>
158 auto Concat (
const Container<ContArgs...>& containers) -> std::decay_t<
decltype (*containers.begin ())>
160 std::decay_t<
decltype (*containers.begin ())> result;
161 for (
const auto& cont : containers)
162 for (
const auto& item : cont)
167 template<
typename Cont,
typename F>
170 return Concat (
Map (std::forward<Cont> (c), std::forward<F> (f)));
173 template<
template<
typename>
class Container,
typename T>
174 Container<Container<T>>
SplitInto (
size_t numChunks,
const Container<T>& container)
176 Container<Container<T>> result;
178 const size_t chunkSize = container.size () / numChunks;
179 for (
size_t i = 0; i < numChunks; ++i)
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);
188 const auto lastStart = container.begin () + chunkSize * numChunks;
189 const auto lastEnd = container.end ();
190 std::copy (lastStart, lastEnd, std::back_inserter (result.front ()));
195 template<
typename Cont>
198 std::sort (cont.begin (), cont.end ());
199 return std::forward<Cont> (cont);
202 constexpr auto Id = [] (
auto&& t) ->
decltype (
auto) {
return std::forward<decltype (t)> (t); };
207 return [r] (
const auto& left,
const auto& right) {
return std::invoke (r, left) < std::invoke (r, right); };
213 return [r] (
const auto& left,
const auto& right) {
return std::invoke (r, left) == std::invoke (r, right); };
216 constexpr auto Apply = [] (
const auto& t) {
return t (); };
218 constexpr auto Fst = [] (
const auto& pair) {
return pair.first; };
220 constexpr auto Snd = [] (
const auto& pair) {
return pair.second; };
225 return [f = std::forward<F> (f)] (
const auto& pair) {
return std::invoke (f, pair.first); };
231 return [f = std::forward<F> (f)] (
const auto& pair) {
return std::invoke (f, pair.second); };
void Append(Res &result, T &&val) noexcept
auto MapImpl(Container &&c, F f)
Container< T > Filter(const Container< T > &c, F f)
constexpr auto ZipWith(Tup1 &&tup1, auto &&sep, Tup2 &&tup2) noexcept
auto ConcatMap(Cont &&c, F &&f)
Container< T > Concat(const Container< Container< T > > &containers)
typename WrapType< T >::type WrapType_t
decltype(auto) Sorted(Cont &&cont)
auto Zip(const Container< T1 > &c1, const Container< T2 > &c2) -> Container< Pair< T1, T2 > >
auto Map(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
auto MapAs(Container &&c, F &&f) noexcept(noexcept(std::is_nothrow_invocable_v< F, decltype(*c.begin())>))
Container< Container< T > > SplitInto(size_t numChunks, const Container< T > &container)