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