version 0.4
algorithms.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2021-2024 The Ikarus Developers mueller@ibb.uni-stuttgart.de
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
10#pragma once
11
12// This file contains stl-like algorithms
13#include <iosfwd>
14#include <ranges>
15
17namespace Ikarus::utils {
18
28 void makeUniqueAndSort(std::ranges::random_access_range auto& r) {
29 sort(r.begin(), r.end());
30 r.erase(std::unique(r.begin(), r.end()), r.end());
31 }
32
43 template <typename Value>
44 auto appendUnique(std::ranges::random_access_range auto& r, Value&& v) {
45 static_assert(std::is_same_v<typename decltype(begin(r))::value_type, std::remove_reference_t<decltype(v)>>);
46 const auto it = find(begin(r), end(r), v);
47 size_t index = std::distance(begin(r), it);
48 if (it == end(r)) r.push_back(std::forward<Value>(v));
49
50 return index;
51 }
52
62 template <class Container>
63 void printContent(Container&& c, std::ostream& os = std::cout) {
64 std::ranges::for_each(c, [&os](auto&& var) { os << var << '\n'; });
65 }
66
75 template <class Container>
76 auto transformValueRangeToPointerRange(Container& cont) {
77 auto transformValueToPointer = [](auto&& obj) { return &obj; };
78 return (std::ranges::subrange(cont.begin(), cont.end()) | std::views::transform(transformValueToPointer));
79 }
80
90 template <class Container>
92 auto transformValueToPointer = [](auto&& obj) -> auto& { return *obj; };
93 return (std::ranges::subrange(cont.begin(), cont.end()) | std::views::transform(transformValueToPointer));
94 }
95
96#ifndef DOXYGEN
97 // Forward declare functions
98 template <typename... Types>
99 auto makeNestedTupleFlat(std::tuple<Types...> tup);
100#endif
101
102 namespace Impl {
103 template <class Tuple, std::size_t... I>
104 constexpr auto makeTupleSubsetImpl(Tuple&& t, std::index_sequence<I...>) {
105 return std::make_tuple(std::get<I>(std::forward<Tuple>(t))...);
106 }
107
108 template <class Tuple, std::size_t... I>
109 constexpr auto makeTupleFromTupleIndicesImpl(Tuple&& t, std::index_sequence<I...>) {
110 return std::make_tuple(std::get<I>(std::forward<Tuple>(t))...);
111 }
112
113 template <typename T, typename... Ts>
114 struct uniqueImpl : std::type_identity<T> {};
115
116 template <typename... Ts, typename U, typename... Us>
117 struct uniqueImpl<std::tuple<Ts...>, U, Us...>
118 : std::conditional_t<(std::is_same_v<U, Ts> || ...), uniqueImpl<std::tuple<Ts...>, Us...>,
119 uniqueImpl<std::tuple<Ts..., U>, Us...>> {};
120
121 template <typename... Ts>
122 using unique_tupleImpl = typename uniqueImpl<std::tuple<>, Ts...>::type;
123
124 template <typename T, typename... Types>
125 auto makeNestedTupleFlatImpl() {
126 constexpr bool isTuple = traits::isSpecialization<std::tuple, T>::value;
127 if constexpr (sizeof...(Types) > 0) {
128 if constexpr (isTuple)
129 return std::tuple_cat(makeNestedTupleFlat(T()), makeNestedTupleFlatImpl<Types...>());
130 else
131 return std::tuple_cat(std::make_tuple(T()), makeNestedTupleFlatImpl<Types...>());
132 } else {
133 if constexpr (isTuple)
134 return makeNestedTupleFlat(T());
135 else
136 return std::make_tuple(T());
137 }
138 }
139
140 template <typename T, typename... Types>
141 auto makeNestedTupleFlatAndStoreReferencesImpl(const std::tuple<T, Types...>& tup) {
142 constexpr bool isTuple = traits::isSpecialization<std::tuple, std::remove_cvref_t<T>>::value;
143 if constexpr (sizeof...(Types) > 0) {
144 if constexpr (isTuple)
145 return std::tuple_cat(
146 makeNestedTupleFlatAndStoreReferencesImpl(std::get<0>(tup)),
147 std::apply(
148 [](const T&, const Types&... args) {
149 return makeNestedTupleFlatAndStoreReferencesImpl(std::make_tuple(std::cref(args)...));
150 },
151 tup));
152 else
153 return std::tuple_cat(
154 std::make_tuple(std::cref(std::get<0>(tup))),
155 std::apply(
156 [](const T&, const Types&... args) {
157 return makeNestedTupleFlatAndStoreReferencesImpl(std::make_tuple(std::cref(args)...));
158 },
159 tup));
160 } else {
161 if constexpr (isTuple)
162 return makeNestedTupleFlatAndStoreReferencesImpl(std::get<0>(tup));
163 else
164 return std::make_tuple(std::cref(std::get<0>(tup)));
165 }
166 }
167
168 template <typename T, typename... Types>
169 auto makeNestedTupleFlatAndStoreReferencesNonConstImpl(const std::tuple<T, Types...>& tupconst) {
170 auto& tup = const_cast<std::tuple<T, Types...>&>(tupconst);
171 constexpr bool isTuple = traits::isSpecialization<std::tuple, std::remove_cvref_t<T>>::value;
172 if constexpr (sizeof...(Types) > 0) {
173 if constexpr (isTuple)
174 return std::tuple_cat(
175 makeNestedTupleFlatAndStoreReferencesNonConstImpl(std::get<0>(tup)),
176 std::apply(
177 [](T&, Types&... args) {
178 return makeNestedTupleFlatAndStoreReferencesNonConstImpl(std::make_tuple(std::ref(args)...));
179 },
180 tup));
181 else
182 return std::tuple_cat(
183 std::make_tuple(std::ref(std::get<0>(tup))),
184 std::apply(
185 [](T&, Types&... args) {
186 return makeNestedTupleFlatAndStoreReferencesNonConstImpl(std::make_tuple(std::ref(args)...));
187 },
188 tup));
189 } else {
190 if constexpr (isTuple)
191 return makeNestedTupleFlatAndStoreReferencesNonConstImpl(std::get<0>(tup));
192 else
193 return std::make_tuple(std::ref(std::get<0>(tup)));
194 }
195 }
196
197 } // namespace Impl
198
214 template <typename Tuple, typename Predicate>
215 constexpr size_t find_if(Tuple&& tuple, Predicate pred) {
216 size_t index = std::tuple_size<std::remove_reference_t<Tuple>>::value;
217 size_t currentIndex = 0;
218 bool found = false;
219
220 Dune::Hybrid::forEach(tuple, [&](auto&& value) {
221 if (!found && pred(value)) {
222 index = currentIndex;
223 found = true;
224 }
225 ++currentIndex;
226 });
227 return index;
228 }
229
242 template <typename Tuple, typename Predicate>
243 bool none_of(Tuple&& tuple, Predicate pred) {
244 return find_if(tuple, pred) == std::tuple_size<std::decay_t<Tuple>>::value;
245 }
246
259 template <typename Tuple, typename Predicate>
260 bool any_of(Tuple&& tuple, Predicate pred) {
261 return !none_of(tuple, pred);
262 }
263
278 template <typename Tuple, typename Predicate>
279 auto filter(Tuple&& tuple, Predicate pred) {
280 return std::apply(
281 [&pred](auto... ts) {
282 return std::tuple_cat(std::conditional_t<pred(ts), std::tuple<decltype(ts)>, std::tuple<>>{}...);
283 },
284 tuple);
285 }
286
298 template <typename... Types>
299 constexpr auto unique([[maybe_unused]] std::tuple<Types...>&& tuple) {
300 return Impl::unique_tupleImpl<Types...>();
301 }
302
316 template <typename Tuple, typename Predicate>
317 constexpr size_t count_if(Tuple&& tuple, Predicate pred) {
318 size_t counter = 0;
319 Dune::Hybrid::forEach(tuple, [&](auto&& value) {
320 if (pred(value)) ++counter;
321 });
322 return counter;
323 }
324
337 template <template <auto...> class Type, typename Tuple>
338 constexpr int findTypeSpecialization() {
339 return find_if(std::remove_cvref_t<Tuple>(), []<typename T>(T&&) {
340 return traits::isSpecializationNonTypes<Type, std::remove_cvref_t<T>>::value;
341 });
342 }
343
356 template <template <auto...> class Type, typename Tuple>
357 auto getSpecialization(Tuple&& tuple) {
358 constexpr int index = findTypeSpecialization<Type, Tuple>();
359 static_assert(index < std::tuple_size_v<std::remove_cvref_t<Tuple>>,
360 "The found index has to be smaller than the tuple size");
361 return std::get<index>(tuple);
362 }
363
377 template <template <auto...> class Type, typename Tuple>
378 constexpr bool hasTypeSpecialization() {
379 return (
380 find_if(std::remove_cvref_t<Tuple>(),
381 []<typename T>(T&&) { return traits::isSpecializationNonTypes<Type, std::remove_cvref_t<T>>::value; })
382 < std::tuple_size_v<std::remove_cvref_t<Tuple>>);
383 }
384
396 template <template <auto...> class Type, typename Tuple>
397 constexpr bool countTypeSpecialization() {
398 return count_if(
399 Tuple(), []<typename T>(T&&) { return traits::isSpecializationNonTypes<Type, std::remove_cvref_t<T>>::value; });
400 }
401
413 template <template <auto...> class Type, typename Tuple>
414 static constexpr bool countTypeSpecialization_v = countTypeSpecialization<Type, Tuple>();
415
428 template <int N, class Tuple>
429 constexpr auto makeTupleSubset(Tuple&& t) {
430 static_assert(N < std::tuple_size_v<std::remove_reference_t<Tuple>>,
431 "The requested size needs to be smaller than the size of the tuple.");
432
433 return Impl::makeTupleSubsetImpl(std::forward<Tuple>(t), std::make_index_sequence<N>{});
434 }
435
449 template <class Tuple, std::size_t... I>
450 constexpr auto makeTupleFromTupleIndices(Tuple&& t) {
451 return Impl::makeTupleFromTupleIndicesImpl(std::forward<Tuple>(t), std::index_sequence<I...>{});
452 }
453
461 template <typename... Types>
462 auto makeNestedTupleFlat(std::tuple<Types...>) {
463 return decltype(Impl::makeNestedTupleFlatImpl<Types...>())();
464 }
465
475 template <typename Tuple>
477 if constexpr (std::tuple_size_v<std::remove_cvref_t<Tuple>> == 0)
478 return tup;
479 else if constexpr (!std::is_const_v<std::remove_reference_t<Tuple>>)
480 return Impl::makeNestedTupleFlatAndStoreReferencesNonConstImpl(std::forward<Tuple>(tup));
481 else
482 return Impl::makeNestedTupleFlatAndStoreReferencesImpl(std::forward<Tuple>(tup));
483 }
484
492 template <typename T>
493 requires traits::Pointer<T>
495 if constexpr (!std::is_same_v<T, std::nullptr_t>)
496 return *v;
497 else
498 return std::nullopt;
499 }
500
501} // namespace Ikarus::utils
Contains stl-like type traits.
auto getSpecialization(Tuple &&tuple)
Gets the specialization of the given template type from the tuple.
Definition: algorithms.hh:357
void printContent(Container &&c, std::ostream &os=std::cout)
Prints the contents of a container to the specified output stream.
Definition: algorithms.hh:63
constexpr auto unique(std::tuple< Types... > &&tuple)
Creates a tuple with unique types from the given tuple.
Definition: algorithms.hh:299
constexpr auto makeTupleSubset(Tuple &&t)
Creates a subset tuple with the first N elements from the given tuple.
Definition: algorithms.hh:429
bool none_of(Tuple &&tuple, Predicate pred)
Checks if none of the elements in the tuple satisfy a given predicate.
Definition: algorithms.hh:243
auto transformValueRangeToPointerRange(Container &cont)
Transforms a value range to a pointer range.
Definition: algorithms.hh:76
constexpr int findTypeSpecialization()
Finds the index of the first element in the tuple that is a specialization of the given template type...
Definition: algorithms.hh:338
static constexpr bool countTypeSpecialization_v
Variable template for counting the occurrences of a specialization of a template type in a tuple.
Definition: algorithms.hh:414
void makeUniqueAndSort(std::ranges::random_access_range auto &r)
Sorts and removes duplicate elements from a random access range.*.
Definition: algorithms.hh:28
auto appendUnique(std::ranges::random_access_range auto &r, Value &&v)
Appends a value to the range if it is not already present.
Definition: algorithms.hh:44
auto transformPointerRangeToReferenceRange(Container &cont)
Transforms a pointer range to a reference range.
Definition: algorithms.hh:91
bool any_of(Tuple &&tuple, Predicate pred)
Checks if any of the elements in the tuple satisfy a given predicate.
Definition: algorithms.hh:260
auto filter(Tuple &&tuple, Predicate pred)
Filters the elements of a tuple based on a given predicate.
Definition: algorithms.hh:279
constexpr bool countTypeSpecialization()
Counts the occurrences of a specialization of a template type in a tuple.
Definition: algorithms.hh:397
constexpr size_t count_if(Tuple &&tuple, Predicate pred)
Counts the number of elements in the tuple satisfying the given predicate.
Definition: algorithms.hh:317
constexpr bool hasTypeSpecialization()
Checks if a tuple has a specialization of a template type.
Definition: algorithms.hh:378
constexpr auto makeTupleFromTupleIndices(Tuple &&t)
Creates a new tuple using indices from the original tuple.
Definition: algorithms.hh:450
constexpr size_t find_if(Tuple &&tuple, Predicate pred)
Finds the index of the first element in the tuple satisfying a predicate.
Definition: algorithms.hh:215
Definition: algorithms.hh:17
auto makeNestedTupleFlatAndStoreReferences(Tuple &&tup)
Creates a flattened nested tuple and stores references.
Definition: algorithms.hh:476
auto makeNestedTupleFlat(std::tuple< Types... >)
Creates a flattened nested tuple.
Definition: algorithms.hh:462
auto & returnReferenceOrNulloptIfObjectIsNullPtr(T v)
Returns a reference or std::nullopt if the object is a nullptr.
Definition: algorithms.hh:494
Concept to check if a type is a pointer or nullptr_t.
Definition: traits.hh:23