stl_util.h Source File

CPP API: stl_util.h Source File
stl_util.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Daniel Abele
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_UTIL_STL_UTIL_H
21 #define MIO_UTIL_STL_UTIL_H
22 
23 #include <array>
24 #include <concepts>
25 #include <numeric>
26 #include <vector>
27 #include <algorithm>
28 #include <utility>
29 #include <iterator>
30 #include <iostream>
31 #include <iomanip>
32 #include <sstream>
33 #include <cstring>
34 #include <cassert>
35 #include <memory>
36 
37 namespace mio
38 {
39 
49 inline std::ostream& set_ostream_format(std::ostream& out, size_t width, size_t precision, char fill = ' ')
50 {
51  // Note: ostream& operator<< returns a reference to itself
52  return out << std::setw(width) << std::fixed << std::setprecision(precision) << std::setfill(fill);
53 }
54 
65 template <typename T, typename Pred>
66 void insert_sorted_replace(std::vector<T>& vec, T const& item, Pred pred)
67 {
68  auto bounds = std::equal_range(begin(vec), end(vec), item, pred);
69  auto lb = bounds.first;
70  auto ub = bounds.second;
71  assert(ub - lb <= 1); //input vector contains at most one item that is equal to the new item
72  if (ub - lb == 1) {
73  *lb = item;
74  return;
75  }
76  else {
77  vec.insert(lb, item);
78  return;
79  }
80 }
81 
82 template <typename T>
83 void insert_sorted_replace(std::vector<T>& vec, T const& item)
84 {
85  return insert_sorted_replace(vec, item, std::less<T>());
86 }
87 
95 template <class Iterator, class Sentinel = Iterator>
96  requires std::input_or_output_iterator<Iterator> && std::input_or_output_iterator<Sentinel> &&
97  std::equality_comparable_with<Iterator, Sentinel>
98 class Range
99 {
100  // TODO: Make this a thin wrapper for std::ranges::subrange, once we have the ranges library (min libc++ version 16)
101 public:
102  // Type definitions for STL compatible containers.
103  using iterator = Iterator;
105  using reverse_iterator = std::reverse_iterator<iterator>;
106  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
107  using value_type = typename std::iterator_traits<iterator>::value_type;
108  using reference = typename std::iterator_traits<iterator>::reference;
109 
111  Range(Iterator begin, Sentinel end)
112  : m_iterator(std::move(begin))
113  , m_sentinel(std::move(end))
114  {
115  }
117  template <class T>
118  Range(T&& range)
119  : m_iterator(std::forward<T>(range).begin())
120  , m_sentinel(std::forward<T>(range).end())
121  {
122  }
124  template <class I, class S>
125  Range(std::pair<I, S> iterator_pair)
126  : m_iterator(std::move(iterator_pair).first)
127  , m_sentinel(std::move(iterator_pair).second)
128  {
129  }
130 
132  Iterator begin() const
133  {
134  return m_iterator;
135  }
137  Sentinel end() const
138  {
139  return m_sentinel;
140  }
141 
143  reference front() const
144  requires std::forward_iterator<iterator>
145  {
146  return *(begin());
147  }
149  reference back() const
150  requires std::bidirectional_iterator<iterator>
151  {
152  return *(--end());
153  }
154 
156  size_t size() const
157  {
158  return static_cast<size_t>(std::distance(begin(), end()));
159  }
161  bool empty() const
162  {
163  return size() == 0;
164  }
165 
172  reference operator[](size_t index) const
173  {
174  assert(index < size());
175  auto it = begin();
176  std::advance(it, index);
177  return *it;
178  }
179 
181  decltype(auto) rbegin() const
182  requires std::bidirectional_iterator<iterator>
183  {
184  return std::make_reverse_iterator(end());
185  }
187  decltype(auto) rend() const
188  requires std::bidirectional_iterator<iterator>
189  {
190  return std::make_reverse_iterator(begin());
191  }
192 
193 private:
194  Iterator m_iterator;
195  Sentinel m_sentinel;
196 };
197 
199 template <class I, class S>
200 Range(std::pair<I, S> iterator_pair) -> Range<I, S>;
201 
203 template <class T>
204 Range(T&& range) -> Range<decltype(range.begin()), decltype(range.end())>;
205 
207 template <class T>
208 concept HasOstreamOperator = requires(std::ostream os, T t) { os << t; };
209 
210 namespace details
211 {
215 inline size_t string_length(const char* str)
216 {
217  return std::strlen(str);
218 }
219 
223 template <class String>
224 size_t string_length(String&& str)
225 {
226  return str.length();
227 }
228 
232 inline void path_join_rec(std::stringstream&, bool)
233 {
234 }
235 
243 template <class Head, class... Tail>
244 void path_join_rec(std::stringstream& ss, bool writeSeparator, Head&& head, Tail&&... tail)
245 {
246  if (writeSeparator) {
247  ss << '/';
248  }
249  ss << head;
250  path_join_rec(ss, string_length(head) > 0 && head[string_length(head) - 1] != '/', tail...);
251 }
252 
253 } // namespace details
254 
267 template <class String, class... Strings>
268 std::string path_join(String&& base, Strings&&... app)
269 {
270  std::stringstream ss;
271  details::path_join_rec(ss, false, base, app...);
272  auto path = ss.str();
273  return path;
274 }
275 
284 template <class U, class T>
285 std::unique_ptr<U> dynamic_unique_ptr_cast(std::unique_ptr<T>&& base_ptr)
286 {
287  auto tmp_base_ptr = std::move(base_ptr);
288  U* tmp = dynamic_cast<U*>(tmp_base_ptr.get());
289  std::unique_ptr<U> derived_ptr;
290  if (tmp != nullptr) {
291  tmp_base_ptr.release();
292  derived_ptr.reset(tmp);
293  }
294  return derived_ptr;
295 }
296 
300 template <class Iter, class Pred>
301 bool contains(Iter b, Iter e, Pred p)
302 {
303  return find_if(b, e, p) != e;
304 }
305 
318 template <class T>
319 constexpr std::array<T, size_t(T::Count)> enum_members()
320 {
321  auto enum_members = std::array<T, size_t(T::Count)>{};
322  auto indices = std::array<std::underlying_type_t<T>, size_t(T::Count)>{};
323  std::iota(indices.begin(), indices.end(), std::underlying_type_t<T>(0));
324  std::transform(indices.begin(), indices.end(), enum_members.begin(), [](auto i) {
325  return T(i);
326  });
327  return enum_members;
328 }
329 
337 template <class T>
338 using VectorRange =
339  std::conditional_t<std::is_const_v<T>,
342 
343 } // namespace mio
344 
345 #endif // MIO_UTIL_STL_UTIL_H
A range of items defined by two iterators.
Definition: stl_util.h:99
std::reverse_iterator< iterator > reverse_iterator
Definition: stl_util.h:105
Range(Iterator begin, Sentinel end)
Directly construct a Range from two iterators.
Definition: stl_util.h:111
Iterator iterator
Definition: stl_util.h:103
Range(std::pair< I, S > iterator_pair)
Construct a Range from an std::pair of iterators.
Definition: stl_util.h:125
typename std::iterator_traits< iterator >::reference reference
Definition: stl_util.h:108
iterator const_iterator
Definition: stl_util.h:104
reference front() const requires std Sentinel m_sentinel
Get a reference to the first element in the range.
Definition: stl_util.h:143
Range(T &&range)
Construct a Range from another range.
Definition: stl_util.h:118
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: stl_util.h:106
Sentinel end() const
Get an iterator at the end of the range, pointing to one element after the last in the range.
Definition: stl_util.h:137
Iterator begin() const
Get an iterator to the start of the range, pointing at the first element of the range.
Definition: stl_util.h:132
typename std::iterator_traits< iterator >::value_type value_type
Definition: stl_util.h:107
size_t string_length(const char *str)
length of a null terminated C string
Definition: stl_util.h:215
void path_join_rec(std::stringstream &, bool)
breaks the recursion of path_join_rec.
Definition: stl_util.h:232
int size(Comm comm)
Return the size of the given communicator.
Definition: miompi.cpp:75
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires details::IsElementReference< M > RowMajorIterator< M, false > end(M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:449
Range(std::pair< I, S > iterator_pair) -> Range< I, S >
Deduction guide to correctly deduce range type when constructed from a pair.
auto i
Definition: io.h:809
concept HasOstreamOperator
Concept to check if type T has an existing stream output operator "<<".
Definition: stl_util.h:208
std::unique_ptr< U > dynamic_unique_ptr_cast(std::unique_ptr< T > &&base_ptr)
converts a unique_ptr<T> to unique_ptr.
Definition: stl_util.h:285
std::conditional_t< std::is_const_v< T >, typename mio::Range< typename std::vector< std::remove_const_t< T > >::const_iterator >, typename mio::Range< typename std::vector< std::remove_const_t< T > >::iterator > > VectorRange
Defines generic Range type for IterPair of a vector.
Definition: stl_util.h:341
requires(!std::is_trivial_v< T >) void BinarySerializerObject
Definition: binary_serializer.h:333
std::ostream & set_ostream_format(std::ostream &out, size_t width, size_t precision, char fill=' ')
Adds manipulators for width, (fixed) precision and fill character to an ostream.
Definition: stl_util.h:49
constexpr std::array< T, size_t(T::Count)> enum_members()
Get an std::array that contains all members of an enum class.
Definition: stl_util.h:319
requires details::IsElementReference< M > RowMajorIterator< M, false > begin(M &m)
create a non-const iterator to first element of the matrix m.
Definition: eigen_util.h:421
std::string path_join(String &&base, Strings &&... app)
join one ore more strings with path separators.
Definition: stl_util.h:268
void insert_sorted_replace(std::vector< T > &vec, T const &item, Pred pred)
inserts element in a sorted vector, replacing items that are equal precondition: elements in the vect...
Definition: stl_util.h:66
bool contains(Iter b, Iter e, Pred p)
checks if there is an element in this range that matches a predicate
Definition: stl_util.h:301
Definition: io.h:94