AMDiS  0.3
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 
344  template <class RR>
345  constexpr MappedRangeView(RR&& rawRange, F const& f) noexcept
346  : rawRange_(FWD(rawRange))
347  , f_(f)
348  {}
349 
358  constexpr const_iterator begin() const noexcept
359  {
360  return const_iterator(rawRange_.begin(), &f_);
361  }
362 
363  constexpr iterator begin() noexcept
364  {
365  return iterator(rawRange_.begin(), &f_);
366  }
367 
374  template <class RR = R, class = decltype(std::declval<RR>().size())>
375  constexpr auto size() const noexcept
376  {
377  return rawRange_.size();
378  }
379 
381  template <class RR = R, class = decltype(std::declval<RR>().operator[](std::size_t(0)))>
382  decltype(auto) operator[](std::size_t i) const
383  {
384  return f_(rawRange_[i]);
385  }
386 
390  constexpr bool empty() const noexcept
391  {
392  return rawRange_.begin() == rawRange_.end();
393  }
394 
403  constexpr const_iterator end() const noexcept
404  {
405  return const_iterator(rawRange_.end(), &f_);
406  }
407 
408  constexpr iterator end() noexcept
409  {
410  return iterator(rawRange_.end(), &f_);
411  }
412 
413  private:
414  R rawRange_;
415  F f_;
416  };
417 
418 
444  template <class R, class F>
445  auto mappedRangeView(R&& range, F const& f)
446  {
447  return MappedRangeView<R, F>(FWD(range), f);
448  }
449 
450 
451  template <class Iter, class F>
452  auto mappedIterator(Iter it, F const* f)
453  {
454  using iterator = Impl::MappedRangeIterator<Iter, F>;
455  return iterator(it, f);
456  }
457 
458  template <class ConstIter, class F>
459  auto mappedConstIterator(ConstIter it, F const* f)
460  {
461  using const_iterator = Impl::MappedRangeIterator<ConstIter, F>;
462  return const_iterator(it, f);
463  }
464 
465 } // end namespace AMDiS
constexpr bool empty() const noexcept
Checks whether the range is empty.
Definition: MappedRangeView.hpp:390
constexpr const_iterator begin() const noexcept
Obtain a iterator to the first element.
Definition: MappedRangeView.hpp:358
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:403
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
auto mappedRangeView(R &&range, F const &f)
Create a MappedRangeView.
Definition: MappedRangeView.hpp:445
constexpr auto size() const noexcept
Return the number of elements in the range, if availble.
Definition: MappedRangeView.hpp:375
constexpr MappedRangeView(RR &&rawRange, F const &f) noexcept
Construct from range and function.
Definition: MappedRangeView.hpp:345