AMDiS 2.10
The Adaptive Multi-Dimensional Simulation Toolbox
MappedRangeView.hpp
1#pragma once
2
3#include <iterator>
4#include <type_traits>
5
6#include <amdis/common/TypeTraits.hpp>
7
8namespace AMDiS
9{
10 // NOTE: this is a backport of the dune-common TransformedRangeView with added size() function.
11
12 namespace Impl
13 {
14 // Helper class to mimic a pointer for proxy objects.
15 // This is needed to implement operator-> on an iterator
16 // using proxy-values. It stores the proxy value but
17 // provides operator-> like a pointer.
18 template <class ProxyType>
19 class PointerProxy
20 {
21 public:
22 PointerProxy(ProxyType&& p)
23 : p_(p)
24 {}
25
26 ProxyType* operator->()
27 {
28 return &p_;
29 }
30
31 ProxyType p_;
32 };
33
34 // An iterator transforming a wrapped iterator using
35 // an unary function. It inherits the iterator-category
36 // of the underlying iterator.
37 template <class I, class F, class C = typename std::iterator_traits<I>::iterator_category>
38 class MappedRangeIterator;
39
40 template <class I, class F>
41 class MappedRangeIterator<I,F,std::forward_iterator_tag>
42 {
43 public:
44 using iterator_category = std::forward_iterator_tag;
45 using reference = decltype(std::declval<F>()(*(std::declval<I>())));
46 using value_type = std::decay_t<reference>;
47 using pointer = PointerProxy<value_type>;
48
49 // If we later want to allow standalone MappedRangeIterators,
50 // we could customize the FunctionPointer to be a default-constructible,
51 // copy-assignable type storing a function but acting like a pointer
52 // to function.
53 using FunctionPointer = const F*;
54
55 constexpr MappedRangeIterator(const I& it, FunctionPointer f) noexcept
56 : it_(it)
57 , f_(f)
58 {}
59
60 // Explicitly initialize members. Using a plain
61 //
62 // constexpr MappedRangeIterator() noexcept {}
63 //
64 // would default-initialize the members while
65 //
66 // constexpr MappedRangeIterator() noexcept : it_(), f_() {}
67 //
68 // leads to value-initialization. This is a case where
69 // both are really different. If it_ is a raw pointer (i.e. POD)
70 // then default-initialization leaves it uninitialized while
71 // value-initialization zero-initializes it.
72 constexpr MappedRangeIterator() noexcept
73 : it_()
74 , f_()
75 {}
76
77 // Dereferencing returns a value created by the function
78 constexpr reference operator*() const noexcept
79 {
80 return (*f_)(*it_);
81 }
82
83 // Dereferencing returns a value created by the function
84 pointer operator->() const noexcept
85 {
86 return (*f_)(*it_);
87 }
88
89 constexpr MappedRangeIterator& operator=(MappedRangeIterator const&) = default;
90
91 constexpr bool operator==(const MappedRangeIterator& other) const noexcept
92 {
93 return (it_ == other.it_);
94 }
95
96 constexpr bool operator!=(const MappedRangeIterator& other) const noexcept
97 {
98 return (it_ != other.it_);
99 }
100
101 MappedRangeIterator& operator++() noexcept
102 {
103 ++it_;
104 return *this;
105 }
106
107 MappedRangeIterator operator++(int) noexcept
108 {
109 MappedRangeIterator copy(*this);
110 ++(*this);
111 return copy;
112 }
113
114 protected:
115 I it_;
116 FunctionPointer f_;
117 };
118
119
120 template <class I, class F>
121 class MappedRangeIterator<I,F,std::bidirectional_iterator_tag>
122 : public MappedRangeIterator<I,F,std::forward_iterator_tag>
123 {
124 protected:
125 using Base = MappedRangeIterator<I,F,std::forward_iterator_tag>;
126 using Base::it_;
127 using Base::f_;
128 public:
129 using iterator_category = std::bidirectional_iterator_tag;
130 using reference = typename Base::reference;
131 using value_type = typename Base::value_type;
132 using pointer = typename Base::pointer;
133
134 using FunctionPointer = typename Base::FunctionPointer;
135
136 // inheriting constructor
137 using Base::Base;
138
139 // Member functions of the forward_iterator that need
140 // to be redefined because the base class methods return a
141 // forward_iterator.
142 constexpr MappedRangeIterator& operator=(MappedRangeIterator const&) = default;
143
144 MappedRangeIterator& operator++() noexcept
145 {
146 ++it_;
147 return *this;
148 }
149
150 MappedRangeIterator operator++(int) noexcept
151 {
152 MappedRangeIterator copy(*this);
153 ++(*this);
154 return copy;
155 }
156
157 // Additional member functions of bidirectional_iterator
158 MappedRangeIterator& operator--() noexcept
159 {
160 --(this->it_);
161 return *this;
162 }
163
164 MappedRangeIterator operator--(int) noexcept
165 {
166 MappedRangeIterator copy(*this);
167 --(*this);
168 return copy;
169 }
170 };
171
172
173 template <class I, class F>
174 class MappedRangeIterator<I,F,std::random_access_iterator_tag>
175 : public MappedRangeIterator<I,F,std::bidirectional_iterator_tag>
176 {
177 protected:
178 using Base = MappedRangeIterator<I,F,std::bidirectional_iterator_tag>;
179 using Base::it_;
180 using Base::f_;
181 public:
182 using iterator_category = std::random_access_iterator_tag;
183 using reference = typename Base::reference;
184 using value_type = typename Base::value_type;
185 using pointer = typename Base::pointer;
186 using difference_type = typename std::iterator_traits<I>::difference_type;
187
188 using FunctionPointer = typename Base::FunctionPointer;
189
190 // inheriting constructor
191 using Base::Base;
192
193 // Member functions of the forward_iterator that need
194 // to be redefined because the base class methods return a
195 // forward_iterator.
196 constexpr MappedRangeIterator& operator=(MappedRangeIterator const&) = default;
197
198 MappedRangeIterator& operator++() noexcept
199 {
200 ++it_;
201 return *this;
202 }
203
204 MappedRangeIterator operator++(int) noexcept
205 {
206 MappedRangeIterator copy(*this);
207 ++(*this);
208 return copy;
209 }
210
211 // Member functions of the bidirectional_iterator that need
212 // to be redefined because the base class methods return a
213 // bidirectional_iterator.
214 MappedRangeIterator& operator--() noexcept
215 {
216 --(this->it_);
217 return *this;
218 }
219
220 MappedRangeIterator operator--(int) noexcept
221 {
222 MappedRangeIterator copy(*this);
223 --(*this);
224 return copy;
225 }
226
227 // Additional member functions of random_access_iterator
228 MappedRangeIterator& operator+=(difference_type n) noexcept
229 {
230 it_ += n;
231 return *this;
232 }
233
234 MappedRangeIterator& operator-=(difference_type n) noexcept
235 {
236 it_ -= n;
237 return *this;
238 }
239
240 bool operator<(const MappedRangeIterator& other) noexcept
241 {
242 return it_<other.it_;
243 }
244
245 bool operator<=(const MappedRangeIterator& other) noexcept
246 {
247 return it_<=other.it_;
248 }
249
250 bool operator>(const MappedRangeIterator& other) noexcept
251 {
252 return it_>other.it_;
253 }
254
255 bool operator>=(const MappedRangeIterator& other) noexcept
256 {
257 return it_>=other.it_;
258 }
259
260 reference operator[](difference_type n) noexcept
261 {
262 return (*f_)(*(it_+n));
263 }
264
265 friend
266 MappedRangeIterator operator+(const MappedRangeIterator& it, difference_type n) noexcept
267 {
268 return MappedRangeIterator(it.it_+n, it.f_);
269 }
270
271 friend
272 MappedRangeIterator operator+(difference_type n, const MappedRangeIterator& it) noexcept
273 {
274 return MappedRangeIterator(n+it.it_, it.f_);
275 }
276
277 friend
278 MappedRangeIterator operator-(const MappedRangeIterator& it, difference_type n) noexcept
279 {
280 return MappedRangeIterator(it.it_-n, it.f_);
281 }
282
283 friend
284 difference_type operator-(const MappedRangeIterator& first, const MappedRangeIterator& second) noexcept
285 {
286 return first.it_-second.it_;
287 }
288 };
289
290
291 } // namespace Impl
292
293
323 template <class R, class F>
325 {
326 using RawConstIterator = TYPEOF(std::declval<const R>().begin());
327 using RawIterator = TYPEOF(std::declval<R>().begin());
328
329 public:
330
337 using const_iterator = Impl::MappedRangeIterator<RawConstIterator, F>;
338
339 using iterator = Impl::MappedRangeIterator<RawIterator, F>;
340
341 using value_type = typename iterator::value_type;
342
346 template <class RR>
347 constexpr MappedRangeView(RR&& rawRange, F const& f) noexcept
348 : rawRange_(FWD(rawRange))
349 , f_(f)
350 {}
351
360 constexpr const_iterator begin() const noexcept
361 {
362 return const_iterator(rawRange_.begin(), &f_);
363 }
364
365 constexpr iterator begin() noexcept
366 {
367 return iterator(rawRange_.begin(), &f_);
368 }
369
376 template <class RR = R, class = decltype(std::declval<RR>().size())>
377 constexpr auto size() const noexcept
378 {
379 return rawRange_.size();
380 }
381
383 template <class RR = R, class = decltype(std::declval<RR>().operator[](std::size_t(0)))>
384 decltype(auto) operator[](std::size_t i) const
385 {
386 return f_(rawRange_[i]);
387 }
388
392 constexpr bool empty() const noexcept
393 {
394 return rawRange_.begin() == rawRange_.end();
395 }
396
405 constexpr const_iterator end() const noexcept
406 {
407 return const_iterator(rawRange_.end(), &f_);
408 }
409
410 constexpr iterator end() noexcept
411 {
412 return iterator(rawRange_.end(), &f_);
413 }
414
415 private:
416 R rawRange_;
417 F f_;
418 };
419
420
446 template <class R, class F>
447 auto mappedRangeView(R&& range, F const& f)
448 {
449 return MappedRangeView<R, F>(FWD(range), f);
450 }
451
452
453 template <class Iter, class F>
454 auto mappedIterator(Iter it, F const* f)
455 {
456 using iterator = Impl::MappedRangeIterator<Iter, F>;
457 return iterator(it, f);
458 }
459
460 template <class ConstIter, class F>
461 auto mappedConstIterator(ConstIter it, F const* f)
462 {
463 using const_iterator = Impl::MappedRangeIterator<ConstIter, F>;
464 return const_iterator(it, f);
465 }
466
467} // end namespace AMDiS
A range transforming the values of another range on-the-fly.
Definition: MappedRangeView.hpp:325
constexpr const_iterator begin() const noexcept
Obtain a iterator to the first element.
Definition: MappedRangeView.hpp:360
Impl::MappedRangeIterator< RawConstIterator, F > const_iterator
Iterator type.
Definition: MappedRangeView.hpp:337
constexpr const_iterator end() const noexcept
Obtain a iterator past the last element.
Definition: MappedRangeView.hpp:405
constexpr MappedRangeView(RR &&rawRange, F const &f) noexcept
Construct from range and function.
Definition: MappedRangeView.hpp:347
constexpr bool empty() const noexcept
Checks whether the range is empty.
Definition: MappedRangeView.hpp:392
constexpr auto size() const noexcept
Return the number of elements in the range, if availble.
Definition: MappedRangeView.hpp:377