OGS
Algorithm.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <algorithm>
14#include <cassert>
15#include <concepts>
16#include <optional>
17#include <range/v3/algorithm/find_if.hpp>
18#include <range/v3/range/concepts.hpp>
19#include <string>
20#include <typeindex>
21#include <typeinfo>
22#include <utility>
23
24#include "Error.h"
25
26namespace BaseLib
27{
36template <typename T>
37std::vector<T> excludeObjectCopy(
38 std::vector<T> const& src_vec,
39 std::vector<std::size_t> const& exclude_positions)
40{
41 std::vector<T> dest_vec;
42 if (exclude_positions.empty())
43 {
44 dest_vec = src_vec;
45 return dest_vec;
46 }
47
48 assert(exclude_positions.back() < src_vec.size());
49
50 std::copy_n(src_vec.cbegin(), exclude_positions[0],
51 std::back_inserter(dest_vec));
52 for (std::size_t i = 1; i < exclude_positions.size(); ++i)
53 {
54 std::copy_n(src_vec.cbegin() + exclude_positions[i - 1] + 1,
55 exclude_positions[i] - (exclude_positions[i - 1] + 1),
56 std::back_inserter(dest_vec));
57 }
58 std::copy(src_vec.cbegin() + exclude_positions.back() + 1, src_vec.cend(),
59 std::back_inserter(dest_vec));
60
61 return dest_vec;
62}
63
64template <typename T>
65void excludeObjectCopy(std::vector<T> const& src_vec,
66 std::vector<std::size_t> const& exclude_positions,
67 std::vector<T>& dest_vec)
68{
69 dest_vec = excludeObjectCopy(src_vec, exclude_positions);
70}
71
75template <ranges::input_range Range>
76ranges::range_reference_t<Range> findElementOrError(
77 Range& range,
78 std::predicate<ranges::range_reference_t<Range>> auto&& predicate,
79 std::invocable auto error_callback)
80{
81 auto it =
82 ranges::find_if(range, std::forward<decltype(predicate)>(predicate));
83 if (it == ranges::end(range))
84 {
85 error_callback();
87 "Element not found in the input range. The user provided error "
88 "callback is meant not to return. That has not happened.");
89 }
90 return *it;
91}
92
98template <typename Map, typename Key, typename Value>
99void insertIfKeyUniqueElseError(Map& map, Key const& key, Value&& value,
100 std::string const& error_message)
101{
102 auto const inserted = map.emplace(key, std::forward<Value>(value));
103 if (!inserted.second)
104 { // insertion failed, i.e., key already exists
105 OGS_FATAL("{} Key `{}' already exists.", error_message, key);
106 }
107}
108
112template <typename Map, typename Key>
113typename Map::mapped_type& getOrError(Map& map, Key const& key,
114 std::string const& error_message)
115{
116 auto it = map.find(key);
117 if (it == map.end())
118 {
119 if constexpr (std::is_convertible<Key, std::string>::value)
120 {
121 OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message, key);
122 }
123 else
124 {
125 OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message,
126 std::to_string(key));
127 }
128 }
129
130 return it->second;
131}
133template <typename Map, typename Key>
134typename Map::mapped_type const& getOrError(Map const& map, Key const& key,
135 std::string const& error_message)
136{
137 auto it = map.find(key);
138 if (it == map.end())
139 {
140 if constexpr (std::is_convertible<Key, std::string>::value)
141 {
142 OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message, key);
143 }
144 else
145 {
146 OGS_FATAL("{:s} Key `{:s}' does not exist.", error_message,
147 std::to_string(key));
148 }
149 }
150
151 return it->second;
152}
153
157template <typename Container, typename Predicate>
158typename Container::value_type const& getIfOrError(
159 Container const& container,
160 Predicate&& predicate,
161 std::string const& error_message)
162{
163 auto it = std::find_if(begin(container), end(container), predicate);
164 if (it == end(container))
165 {
166 OGS_FATAL("Could not find element matching the predicate: {:s}",
167 error_message);
168 }
169 return *it;
170}
171
174template <typename T>
175void makeVectorUnique(std::vector<T>& v)
176{
177 std::sort(v.begin(), v.end());
178 auto it = std::unique(v.begin(), v.end());
179 v.erase(it, v.end());
180}
181
184template <typename T, class Compare>
185void makeVectorUnique(std::vector<T>& v, Compare comp)
186{
187 std::sort(v.begin(), v.end(), comp);
188 auto it = std::unique(v.begin(), v.end());
189 v.erase(it, v.end());
190}
191
197template <typename ValueType, typename IndexType>
198void reorderVector(std::vector<ValueType>& v,
199 std::vector<IndexType> const& order)
200{
201 std::vector<ValueType> temp_v(v.size());
202 temp_v.swap(v);
203
204 for (std::size_t i = 0; i < order.size(); i++)
205 {
206 std::swap(v[i], temp_v[order[i]]);
207 }
208}
209
210template <typename Container>
211void uniquePushBack(Container& container,
212 typename Container::value_type const& element)
213{
214 if (std::find(container.begin(), container.end(), element) ==
215 container.end())
216 {
217 container.push_back(element);
218 }
219}
220
221template <typename Container>
222std::optional<typename Container::value_type> findFirstNotEqualElement(
223 Container const& container, typename Container::value_type const& element)
224{
225 auto const it =
226 std::find_if_not(container.begin(), container.end(),
227 [&element](typename Container::value_type const& e)
228 { return e == element; });
229 return it == container.end() ? std::nullopt : std::make_optional(*it);
230}
231
237template <typename Container>
238std::size_t findIndex(Container const& container,
239 typename Container::value_type const& element)
240{
241 auto const it = std::find(container.begin(), container.end(), element);
242 if (it == container.end())
243 {
244 return std::numeric_limits<std::size_t>::max();
245 }
246 return std::distance(container.begin(), it);
247}
248
250template <typename T>
251void cleanupVectorElements(std::vector<T*>& items)
252{
253 for (auto item : items)
254 {
255 delete item;
256 }
257 items.clear();
258}
259
267template <typename T1, typename... Args>
268void cleanupVectorElements(std::vector<T1*>& dependent_items, Args&&... args)
269{
270 cleanupVectorElements(dependent_items);
271 cleanupVectorElements(std::forward<Args>(args)...);
272}
273
275template <typename List>
276constexpr bool any_of(List const& values)
277{
278 // std::any_of is not constexpr enough in some STLs
279 for (auto& value : values)
280 {
281 if (static_cast<bool>(value))
282 {
283 return true;
284 }
285 }
286
287 return false;
288}
289
291template <typename List>
292constexpr bool all_of(List const& values)
293{
294 // std::all_of is not constexpr enough in some STLs
295 for (auto& value : values)
296 {
297 if (!static_cast<bool>(value))
298 {
299 return false;
300 }
301 }
302
303 return true;
304}
305
307template <typename List>
308constexpr bool none_of(List const& values)
309{
310 return !any_of(values);
311}
312
317template <class... Ts>
318struct Overloaded : Ts...
319{
320 using Ts::operator()...;
321};
322#if defined(__clang__)
323#if (__clang_major__ <= 16)
325template <class... Ts>
326Overloaded(Ts...) -> Overloaded<Ts...>;
327#endif
328#endif
329
330} // namespace BaseLib
#define OGS_FATAL(...)
Definition Error.h:26
Wraps a pair of iterators for use as a range in range-based for-loops.
std::vector< T > excludeObjectCopy(std::vector< T > const &src_vec, std::vector< std::size_t > const &exclude_positions)
Definition Algorithm.h:37
Map::mapped_type & getOrError(Map &map, Key const &key, std::string const &error_message)
Definition Algorithm.h:113
std::size_t findIndex(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:238
void insertIfKeyUniqueElseError(Map &map, Key const &key, Value &&value, std::string const &error_message)
Definition Algorithm.h:99
ranges::range_reference_t< Range > findElementOrError(Range &range, std::predicate< ranges::range_reference_t< Range > > auto &&predicate, std::invocable auto error_callback)
Definition Algorithm.h:76
constexpr bool none_of(List const &values)
Checks if none of the elements in the given list are true.
Definition Algorithm.h:308
void cleanupVectorElements(std::vector< T * > &items)
Definition Algorithm.h:251
void uniquePushBack(Container &container, typename Container::value_type const &element)
Definition Algorithm.h:211
constexpr bool all_of(List const &values)
Checks if all of the elements in the given list are true.
Definition Algorithm.h:292
Container::value_type const & getIfOrError(Container const &container, Predicate &&predicate, std::string const &error_message)
Definition Algorithm.h:158
void reorderVector(std::vector< ValueType > &v, std::vector< IndexType > const &order)
Definition Algorithm.h:198
void makeVectorUnique(std::vector< T > &v)
Definition Algorithm.h:175
std::optional< typename Container::value_type > findFirstNotEqualElement(Container const &container, typename Container::value_type const &element)
Definition Algorithm.h:222
constexpr bool any_of(List const &values)
Checks if any of the elements in the given list is true.
Definition Algorithm.h:276