ML 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
19ML_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
63 template <class T, class R, typename I, I (T::*Count)() const, R *(T::*Access)(I) const>
65 {
66 const T* _object;
67
68 public:
69 using value_type = R *;
70
71 explicit ContainerProxy(const T &object)
72 : _object(&object)
73 {
74 }
75
76 ContainerProxy(const ContainerProxy &) = default;
80
82 {
83 public:
84 using iterator_category = std::bidirectional_iterator_tag;
86 using difference_type = ptrdiff_t;
88 using const_pointer = const pointer;
91
92 iterator(const ContainerProxy &proxy, I index)
93 : _index{index}
94 , _proxy{&proxy}
95 {
96 }
97
98 iterator(const iterator &) = default;
99 iterator &operator=(const iterator &) = default;
100 iterator(iterator &&) = default;
102
103 I index() const { return _index; }
104
106 {
107 return (_proxy->_object->*Access)(_index);
108 }
109
111 {
112 return operator*();
113 }
114
116 {
117 _index += 1;
118 return *this;
119 }
120
122 {
123 iterator tmp = *this;
124 ++*this;
125 return tmp;
126 }
127
129 {
130 _index -= 1;
131 return *this;
132 }
133
135 {
136 iterator tmp = *this;
137 --*this;
138 return tmp;
139 }
140
141 friend bool operator==(const iterator &x, const iterator &y)
142 {
143 return x._proxy == y._proxy && x._index == y._index;
144 }
145
146 friend bool operator!=(const iterator &x, const iterator &y)
147 {
148 return !(x == y);
149 }
150
151
152 private:
153 I _index;
154 const ContainerProxy *_proxy;
155 };
156
158
160 {
161 return iterator(*this, 0);
162 }
163
164 iterator end() const
165 {
166 return iterator(*this, (_object->*Count)());
167 }
168
170 {
171 return begin();
172 }
173
175 {
176 return end();
177 }
178 };
179
180/*
181 * Checks if the provided second range is a rotation of the first range. Hereby it uses the predicate
182 * p for comparision the values from the two ranges
183 * If it is a rotation then it returns the rotation point of the second range
184 * If it is not a rotation or both ranges are empty then it returns the end of the second range
185 * \range1 The first range
186 * \range2 The second range
187 * \p The predicate that is used to compare two values
188 */
189 template <typename Range1, typename Range2, typename BinaryPredicate>
190 constexpr typename Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2,
191 BinaryPredicate p)
192 {
193 if (std::size(range1) != std::size(range2))
194 {
195 return std::end(range2);
196 }
197 if (std::size(range1) == 0)
198 {
199 return std::end(range2);
200 }
201 const auto itFind2 = std::find_if(std::begin(range2), std::end(range2),
202 [p, &range1](const auto &v) { return p(*begin(range1), v); });
203
204 if (itFind2 == std::end(range2))
205 {
206 return std::end(range2);
207 }
208 auto resultIts =
209 std::mismatch(itFind2, std::end(range2), std::begin(range1), std::end(range1), p);
210 if (resultIts.first != std::end(range2))
211 {
212 return std::end(range2);
213 }
214 resultIts = std::mismatch(std::begin(range2), itFind2, resultIts.second, std::end(range1), p);
215 if (resultIts.first != itFind2)
216 {
217 return std::end(range2);
218 }
219 return itFind2;
220 }
221
222 /*
223 * Checks if the provided second range is a rotation of the first range
224 * If it is a rotation then it returns the rotation point of the second range
225 * If it is not a rotation or both ranges are empty then it returns the end of the second range
226 * \range1 The first range
227 * \range2 The second range
228 */
229 template <typename Range1, typename Range2>
230 constexpr typename Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2)
231 {
232 if (std::size(range1) != std::size(range2))
233 {
234 return std::end(range2);
235 }
236 if (std::size(range1) == 0)
237 {
238 return std::end(range2);
239 }
240 const auto itFind2 = std::find(std::begin(range2), std::end(range2), *begin(range1));
241
242 if (itFind2 == std::end(range2))
243 {
244 return std::end(range2);
245 }
246 auto resultIts = std::mismatch(itFind2, std::end(range2), std::begin(range1), std::end(range1));
247 if (resultIts.first != std::end(range2))
248 {
249 return std::end(range2);
250 }
251 resultIts = std::mismatch(std::begin(range2), itFind2, resultIts.second, std::end(range1));
252 if (resultIts.first != itFind2)
253 {
254 return std::end(range2);
255 }
256 return itFind2;
257 }
258
259
260ML_UTILS_END_NAMESPACE
friend bool operator==(const iterator &x, const iterator &y)
iterator & operator=(const iterator &)=default
iterator & operator=(iterator &&)=default
friend bool operator!=(const iterator &x, const iterator &y)
std::bidirectional_iterator_tag iterator_category
iterator(iterator &&)=default
iterator(const iterator &)=default
typename ContainerProxy::value_type value_type
iterator(const ContainerProxy &proxy, I index)
This template implements a proxy for container that contain a collection of items that are normally a...
ContainerProxy(const T &object)
iterator begin() const
const_iterator cend() const
ContainerProxy(ContainerProxy &&)=default
ContainerProxy & operator=(ContainerProxy &&)=default
const_iterator cbegin() const
ContainerProxy(const ContainerProxy &)=default
ContainerProxy & operator=(const ContainerProxy &)=default
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
constexpr Is< T > is(T d)
constexpr Range2::const_iterator is_rotated(const Range1 &range1, const Range2 &range2, BinaryPredicate p)
In combination with the in function it returns true, if a passed values is one of a set of possible v...
constexpr bool in(Arg a, Args... args)
constexpr bool in(U a)