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
25 template <class T>
26 struct Is
27 {
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
83 {
84 public:
85 using iterator_category = std::bidirectional_iterator_tag;
89 using const_pointer = const pointer;
92
94 : _index{index}
95 , _proxy{&proxy}
96 {
97 }
98
99 iterator(const iterator &) = default;
100 iterator &operator=(const iterator &) = default;
101 iterator(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
159
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,
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
@ R
@ T
@ U
@ I
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 containers that contain a collection of items normally accessed ...
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
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
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 value is in the set of possible valu...
constexpr bool in(Arg a, Args... args)
constexpr bool in(U a)