header_utils
Loading...
Searching...
No Matches
containers.h
1
4
5#pragma once
6
7#include <vector>
8#include <map>
9#include "ranges.h"
10#include "cpp23.h"
11
12namespace ghassanpl
13{
16
19
21 template <typename T, typename U>
22 constexpr auto push_back_unique(std::vector<T>& vector, U&& value)
23 {
24 const auto it = std::ranges::find(vector, value);
25 if (it == vector.end())
26 {
27 vector.push_back(std::forward<U>(value));
28 return std::prev(vector.end());
29 }
30 return it;
31 }
32
34 template <typename T, typename U>
35 constexpr std::optional<T> erase_single(std::vector<T>& vector, U&& value)
36 {
37 const auto it = std::ranges::find(vector, value);
38 if (it == std::ranges::end(vector))
39 return {};
40 auto&& result = std::move(*it);
41 vector.erase(it);
42 return result;
43 }
44
46 template <typename K, typename V, typename COMP, typename U>
47 constexpr std::optional<V> erase_single(std::map<K, V, COMP>& map, U&& key)
48 {
49 const auto it = map.find(key);
50 if (it == map.end())
51 return {};
52 auto&& result = std::move(it->second);
53 map.erase(it);
54 return result;
55 }
56
58 template <typename T, typename PRED>
59 constexpr std::optional<T> erase_single_if(std::vector<T>& vector, PRED&& pred)
60 {
61 const auto it = std::ranges::find_if(vector, pred);
62 if (it == std::ranges::end(vector))
63 return {};
64 auto&& result = std::move(*it);
65 vector.erase(it);
66 return result;
67 }
68
70 template <typename T, typename U>
71 constexpr std::optional<T> erase_single_swap(std::vector<T>& vector, U&& value)
72 {
73 const auto it = std::ranges::find(vector, value);
74 if (it == std::ranges::end(vector))
75 return {};
76
77 auto&& result = std::exchange(*it, std::move(vector.back()));
78 vector.pop_back();
79 return result;
80 }
81
82
84 template <typename T, typename PRED>
85 constexpr std::vector<T> erase_swap_if(std::vector<T>& vector, PRED&& pred)
86 {
87 std::vector<T> result;
88 size_t i = 0;
89 while (i < vector.size())
90 {
91 if (pred(vector[i]))
92 {
93 result.push_back(std::exchange(vector[i], std::move(vector.back())));
94 vector.pop_back();
95 }
96 else
97 ++i;
98 }
99 return result;
100 }
101
103 template <typename T, typename PRED>
104 constexpr std::optional<T> erase_single_swap_if(std::vector<T>& vector, PRED&& pred)
105 {
106 const auto it = std::ranges::find_if(vector, pred);
107 if (it == std::ranges::end(vector))
108 return {};
109
110 auto result = std::exchange(*it, std::move(vector.back()));
111 vector.pop_back();
112 return result;
113 }
114
116 template <typename T>
117 constexpr std::optional<T> erase_at_swap(std::vector<T>& vector, size_t index)
118 {
119 if (!valid_index(vector, index))
120 return {};
121
122 auto&& result = std::exchange(vector[index], std::move(vector.back()));
123 vector.pop_back();
124 return result;
125 }
126
128 template <typename KEY, typename MAP>
129 [[nodiscard]] auto map_find(MAP& map, KEY&& key)
130 {
131 auto it = map.find(std::forward<KEY>(key));
132 return (it != map.end()) ? &it->second : nullptr;
133 }
134
136 template <typename DEF, typename KEY, typename MAP>
137 [[nodiscard]] auto map_at_or_default(MAP&& map, KEY&& key, DEF&& def)
138 {
139 auto it = map.find(std::forward<KEY>(key));
140 if (it != map.end())
141 return ghassanpl::forward_like<MAP>(it->second);
142 return decltype(it->second){ std::forward<DEF>(def) };
143 }
144
146 template <typename KEY, typename MAP>
147 [[nodiscard]] auto map_at_or_default(MAP&& map, KEY&& key)
148 {
149 auto it = map.find(std::forward<KEY>(key));
150 if (it != map.end())
151 return ghassanpl::forward_like<MAP>(it->second);
152 return decltype(it->second){};
153 }
154
156 template <typename KEY, typename MAP>
157 [[nodiscard]] decltype(auto) map_at(MAP&& map, KEY&& key)
158 {
159 auto it = map.find(std::forward<KEY>(key));
160 if (it != map.end())
161 return ghassanpl::forward_like<MAP>(it->second);
162 throw std::out_of_range("invalid map key");
163 }
164
165 namespace detail
166 {
167 template <typename MAP>
168 inline auto map_key_type(MAP const& val)
169 {
170 auto& [k, v] = *std::begin(val);
171 return decltype(k){};
172 }
173 }
174
176 template <typename MAP, typename VAL>
177 [[nodiscard]] auto map_find_value(MAP& map, VAL const* value)
178 {
179 for (auto& [k, v] : map)
180 {
181 if (&v == value)
182 return &k;
183 }
184 using map_key_type = decltype(detail::map_key_type(map));
185 return (map_key_type const*)nullptr;
186 }
187
190 template <typename K, typename V, typename C, typename VAL>
191 [[nodiscard]] auto at_ptr(std::map<K, V, C> const& map, VAL&& value) { return map_find(map, std::forward<VAL>(value)); }
192
195 template <typename K, typename V, typename C, typename VAL>
196 [[nodiscard]] auto at_ptr(std::map<K, V, C>& map, VAL&& value) { return map_find(map, std::forward<VAL>(value)); }
197
199 /*
200 void move_element(container cont, int from_index, int to_index)
201 {
202 assumingvalidindex(fromindex)
203 assumingvalidindex(toindex)
204
205 if (from_index == to_index)
206 return;
207
208 if (std::abs(from_index - to_index) == 1)
209 {
210 std::swap(mFiles[from_index], mFiles[to_index]);
211 return;
212 }
213
214 if (from_index < to_index)
215 std::rotate(mFiles.begin() + from_index, mFiles.begin() + from_index + 1, mFiles.begin() + to_index + 1);
216 else
217 std::rotate(mFiles.begin() + to_index, mFiles.begin() + from_index, mFiles.begin() + from_index + 1);
218 }
219
220 void move_element_by(container cont, int from_index, int by)
221 {
222 move_element(cont, from_index, clamp(from_index+by, 0, size(cont)));
223 }
224 void move_element_to_front();
225 void move_element_to_back();
226 */
227
229}
auto map_at_or_default(MAP &&map, KEY &&key, DEF &&def)
Finds the value associated with key in the map and retuns it, or def if none found.
Definition containers.h:137
auto at_ptr(std::map< K, V, C > const &map, VAL &&value)
Same as map_find().
Definition containers.h:191
constexpr std::optional< T > erase_single_if(std::vector< T > &vector, PRED &&pred)
Finds a value in the vector by predicate, and erases it.
Definition containers.h:59
constexpr std::vector< T > erase_swap_if(std::vector< T > &vector, PRED &&pred)
Finds and erases a value in vector, not preserving item order (swapping last item to erased).
Definition containers.h:85
constexpr std::optional< T > erase_single_swap_if(std::vector< T > &vector, PRED &&pred)
Finds and erases a value in vector by predicate, not preserving item order (swapping last item to era...
Definition containers.h:104
auto map_find_value(MAP &map, VAL const *value)
Finds the first value of a map element, and returns a pointer to its key, or nullptr if none found.
Definition containers.h:177
constexpr std::optional< T > erase_single(std::vector< T > &vector, U &&value)
Finds a value in the vector, and erases it, but returns the value.
Definition containers.h:35
decltype(auto) map_at(MAP &&map, KEY &&key)
Basically map.at() but works with heterogenous key types.
Definition containers.h:157
auto map_find(MAP &map, KEY &&key)
Finds the value associated with key in the map and retuns a pointer to it, or nullptr if none found.
Definition containers.h:129
constexpr auto push_back_unique(std::vector< T > &vector, U &&value)
Pushes a value to a vector if it doesn't already exists.
Definition containers.h:22
constexpr std::optional< T > erase_single_swap(std::vector< T > &vector, U &&value)
Finds and erases a value in vector, not preserving item order (swapping last item to erased).
Definition containers.h:71
constexpr std::optional< T > erase_at_swap(std::vector< T > &vector, size_t index)
Erases the element at index in vector, not preserving item order (swapping last item to erased).
Definition containers.h:117
constexpr bool valid_index(random_access_range auto &range, std::integral auto index)
Returns whether or not a given integer is a valid index to a random access range.
Definition ranges.h:39
The below code is based on Sun's libm library code, which is licensed under the following license:
Contains functions that return predicates; appropriate for functions like std::all_of.
Definition functional.h:82
Primary namespace for everything in this library.
Definition align+rec2.h:10