Zen C++ Libraries
Zero-dependency re-usable components for C++
Loading...
Searching...
No Matches
algorithm.hpp
1#ifndef ZEN_ALGORITHM_HPP
2#define ZEN_ALGORITHM_HPP
3
4#include <cstddef>
5#include <vector>
6
7#include "zen/config.hpp"
8#include "zen/concepts.hpp"
9
10ZEN_NAMESPACE_START
11
12#define ZEN_CONSTEXPR constexpr
13
14template<typename FnT, std::size_t ...J, typename ...Ts>
15ZEN_CONSTEXPR auto map_tuple_impl(std::tuple<Ts...>& value, std::integer_sequence<std::size_t, J...>, FnT&& f) {
16 return std::make_tuple(f(std::get<J>(value))...);
17}
18
19template<typename FnT, std::size_t ...J, typename ...Ts>
20ZEN_CONSTEXPR auto map_const_tuple_impl(const std::tuple<Ts...>& value, std::integer_sequence<std::size_t, J...>, FnT&& f) {
21 return std::make_tuple(f(std::get<J>(value))...);
22}
23
24template<typename FnT, typename ...Ts>
25ZEN_CONSTEXPR auto cmap(const std::tuple<Ts...>& value, FnT op) {
26 using seq = std::make_index_sequence<std::tuple_size_v<std::tuple<Ts...>>>;
27 return map_const_tuple_impl(value, seq(), std::forward<FnT>(op));
28}
29
30template<typename FnT, typename ...Ts>
31auto map(std::tuple<Ts...>& value, FnT op) {
32 using seq = std::make_index_sequence<std::tuple_size_v<std::tuple<Ts...>>>;
33 return map_tuple_impl(value, seq(), std::forward<FnT>(op));
34}
35
36template<typename T1, typename T2, typename FnT>
37ZEN_CONSTEXPR auto cmap(const std::pair<T1, T2>& value, FnT fn) {
38 return std::make_pair<T1, T2>(fn(value.first), fn(value.second));
39}
40
41template<typename T1, typename T2, typename FnT>
42auto map(std::pair<T1, T2>& value, FnT fn) {
43 return std::make_pair<T1, T2>(fn(value.first), fn(value.second));
44}
45
46template<typename T>
47auto decrement(T& value) {
48 --value;
49}
50
51template<typename T>
52auto increment(T& value) {
53 ++value;
54}
55
56template<typename T>
57T prev_n(T value, std::ptrdiff_t n) {
58 auto curr = value;
59 for (std::ptrdiff_t i = 0; i < n; i++) {
60 decrement(curr);
61 }
62 return curr;
63}
64
65template<typename T, typename = void>
67 static T apply(T& value, std::ptrdiff_t n) {
68 auto curr = value;
69 for (std::ptrdiff_t i = 0; i < n; i++) {
70 increment(curr);
71 }
72 return curr;
73 }
74};
75
76template<typename T>
77T next_n(T& value, std::ptrdiff_t n) {
78 return next_n_impl<T>::apply(value, n);
79}
80
81template<class T, std::size_t N>
83 requires(T t) {
84 typename std::tuple_element_t<N, std::remove_const_t<T>>;
85 { get<N>(t) } -> std::convertible_to<const std::tuple_element_t<N, T>&>;
86 };
87
88template<class T>
89concept tuple_like = !std::is_reference_v<T>
90 && requires(T t) {
91 typename std::tuple_size<T>::type;
92 requires std::derived_from<
93 std::tuple_size<T>,
94 std::integral_constant<std::size_t, std::tuple_size_v<T>>
95 >;
96 }
97 && []<std::size_t... N>(std::index_sequence<N...>) {
98 return (has_tuple_element<T, N> && ...);
99 }(std::make_index_sequence<std::tuple_size_v<T>>());
100
101template <typename F, typename Tuple, std::size_t... I>
102auto tuple_map_impl(F&& f, Tuple&& t, std::index_sequence<I...>) {
103 return std::make_tuple(f(std::get<I>(t))...);
104}
105
106template<typename RangeT, typename FnT, typename OutIterT>
107void transform(const RangeT& range, FnT func, OutIterT iter) {
108 for (auto& element: range) {
109 iter = func(element);
110 }
111}
112
113template<typename T, typename C>
114std::vector<T> collect(const C elements) {
115 std::vector<T> out;
116 for (const auto& element: elements) {
117 out.push_back(element);
118 }
119 return out;
120}
121
122template<range RangeT>
123range_reference_t<RangeT> last(RangeT range) {
124 auto prev = range.begin();
125 auto curr = prev;
126 auto end = range.end();
127 for (;;) {
128 curr++;
129 if (curr == end) {
130 break;
131 }
132 prev = curr;
133 }
134 return *prev;
135}
136
137ZEN_NAMESPACE_END
138
139#endif // of #ifndef ZEN_ALGORITHM_HPP
Definition value.hpp:34
Definition algorithm.hpp:82
Definition concepts.hpp:15
Definition algorithm.hpp:89
Definition algorithm.hpp:66