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 
8 namespace 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
constexpr bool empty() const noexcept
Checks whether the range is empty.
Definition: MappedRangeView.hpp:392
constexpr const_iterator begin() const noexcept
Obtain a iterator to the first element.
Definition: MappedRangeView.hpp:360
A range transforming the values of another range on-the-fly.
Definition: MappedRangeView.hpp:324
Impl::MappedRangeIterator< RawConstIterator, F > const_iterator
Iterator type.
Definition: MappedRangeView.hpp:337
Definition: FieldMatVec.hpp:12
constexpr const_iterator end() const noexcept
Obtain a iterator past the last element.
Definition: MappedRangeView.hpp:405
Definition: AdaptBase.hpp:6
constexpr auto size() const noexcept
Return the number of elements in the range, if availble.
Definition: MappedRangeView.hpp:377
constexpr MappedRangeView(RR &&rawRange, F const &f) noexcept
Construct from range and function.
Definition: MappedRangeView.hpp:347