MeVisLab Toolbox Reference
mlContainerHelpers.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2021, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
15 #include "mlUtilsSystem.h"
16 #include <algorithm>
17 #include <iterator>
18 
19 ML_UTILS_START_NAMESPACE
25  template <class T>
26  struct Is
27  {
28  T d_;
29  template <typename U>
30  constexpr bool in(U a) {
31  return a == d_;
32  }
33 
34  template <class Arg, class... Args>
35  constexpr bool in(Arg a, Args... args) {
36  return in(a) || in(args...);
37  }
38  };
39 
40  template <class T>
41  constexpr Is<T> is(T d) {
42  return Is<T>{d};
43  }
44 
45 
64  template <class T, class R, typename I, I (T::*Count)() const, R *(T::*Access)(I) const>
66  {
67  const T* _object;
68 
69  public:
70  using value_type = R *;
71 
72  explicit ContainerProxy(const T &object)
73  : _object(&object)
74  {
75  }
76 
77  ContainerProxy(const ContainerProxy &) = default;
81 
82  class iterator
83  {
84  public:
85  using iterator_category = std::bidirectional_iterator_tag;
87  using difference_type = ptrdiff_t;
89  using const_pointer = const pointer;
91  using const_reference = const reference;
92 
93  iterator(const ContainerProxy &proxy, I index)
94  : _index{index}
95  , _proxy{&proxy}
96  {
97  }
98 
99  iterator(const iterator &) = default;
100  iterator &operator=(const iterator &) = default;
101  iterator(iterator &&) = default;
102  iterator &operator=(iterator &&) = default;
103 
104  I index() const { return _index; }
105 
107  {
108  return (_proxy->_object->*Access)(_index);
109  }
110 
112  {
113  return operator*();
114  }
115 
117  {
118  _index += 1;
119  return *this;
120  }
121 
123  {
124  iterator tmp = *this;
125  ++*this;
126  return tmp;
127  }
128 
130  {
131  _index -= 1;
132  return *this;
133  }
134 
136  {
137  iterator tmp = *this;
138  --*this;
139  return tmp;
140  }
141 
142  friend bool operator==(const iterator &x, const iterator &y)
143  {
144  return x._proxy == y._proxy && x._index == y._index;
145  }
146 
147  friend bool operator!=(const iterator &x, const iterator &y)
148  {
149  return !(x == y);
150  }
151 
152 
153  private:
154  I _index;
155  const ContainerProxy *_proxy;
156  };
157 
158  using const_iterator = const iterator;
159 
160  iterator begin() const
161  {
162  return iterator(*this, 0);
163  }
164 
165  iterator end() const
166  {
167  return iterator(*this, (_object->*Count)());
168  }
169 
171  {
172  return begin();
173  }
174 
176  {
177  return end();
178  }
179  };
180 
181 /*
182  * Checks whether the provided second range is a rotation of the first range. Hereby it uses the predicate
183  * \p p to compare the values of the two ranges.
184  * If it is a rotation, then it returns the rotation point of the second range.
185  * If it is not a rotation or both ranges are empty, then it returns the end of the second range.
186  * \range1 The first range
187  * \range2 The second range
188  * \p The predicate that is used to compare two values
189  */
190  template <typename Range1, typename Range2, typename BinaryPredicate>
191  constexpr typename Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2,
192  BinaryPredicate p)
193  {
194  if (std::size(range1) != std::size(range2))
195  {
196  return std::end(range2);
197  }
198  if (std::size(range1) == 0)
199  {
200  return std::end(range2);
201  }
202  const auto itFind2 = std::find_if(std::begin(range2), std::end(range2),
203  [p, &range1](const auto &v) { return p(*begin(range1), v); });
204 
205  if (itFind2 == std::end(range2))
206  {
207  return std::end(range2);
208  }
209  auto resultIts =
210  std::mismatch(itFind2, std::end(range2), std::begin(range1), std::end(range1), p);
211  if (resultIts.first != std::end(range2))
212  {
213  return std::end(range2);
214  }
215  resultIts = std::mismatch(std::begin(range2), itFind2, resultIts.second, std::end(range1), p);
216  if (resultIts.first != itFind2)
217  {
218  return std::end(range2);
219  }
220  return itFind2;
221  }
222 
223  /*
224  * Checks whether the provided second range is a rotation of the first range.
225  * If it is a rotation, then it returns the rotation point of the second range.
226  * If it is not a rotation or both ranges are empty, then it returns the end of the second range.
227  * \range1 The first range
228  * \range2 The second range
229  */
230  template <typename Range1, typename Range2>
231  constexpr typename Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2)
232  {
233  if (std::size(range1) != std::size(range2))
234  {
235  return std::end(range2);
236  }
237  if (std::size(range1) == 0)
238  {
239  return std::end(range2);
240  }
241  const auto itFind2 = std::find(std::begin(range2), std::end(range2), *begin(range1));
242 
243  if (itFind2 == std::end(range2))
244  {
245  return std::end(range2);
246  }
247  auto resultIts = std::mismatch(itFind2, std::end(range2), std::begin(range1), std::end(range1));
248  if (resultIts.first != std::end(range2))
249  {
250  return std::end(range2);
251  }
252  resultIts = std::mismatch(std::begin(range2), itFind2, resultIts.second, std::end(range1));
253  if (resultIts.first != itFind2)
254  {
255  return std::end(range2);
256  }
257  return itFind2;
258  }
259 
260 
261 ML_UTILS_END_NAMESPACE
@ R
Definition: SoKeyGrabber.h:69
@ T
Definition: SoKeyGrabber.h:71
@ U
Definition: SoKeyGrabber.h:72
@ I
Definition: SoKeyGrabber.h:60
friend bool operator==(const iterator &x, const iterator &y)
friend bool operator!=(const iterator &x, const iterator &y)
std::bidirectional_iterator_tag iterator_category
iterator(iterator &&)=default
iterator(const iterator &)=default
iterator & operator=(iterator &&)=default
typename ContainerProxy::value_type value_type
iterator & operator=(const iterator &)=default
iterator(const ContainerProxy &proxy, I index)
This template implements a proxy for containers that contain a collection of items normally accessed ...
ContainerProxy(const T &object)
iterator begin() const
const_iterator cend() const
ContainerProxy & operator=(ContainerProxy &&)=default
ContainerProxy & operator=(const ContainerProxy &)=default
ContainerProxy(ContainerProxy &&)=default
const_iterator cbegin() const
ContainerProxy(const ContainerProxy &)=default
iterator end() const
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
constexpr Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2)
constexpr Is< T > is(T d)
In combination with the in function, it returns true if a passed value is in the set of possible valu...
constexpr bool in(Arg a, Args... args)
constexpr bool in(U a)