DUNE PDELab (git)

vectoriterator.hh
1// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=8 sw=2 sts=2:
3#ifndef DUNE_PDELAB_BACKEND_ISTL_VECTORITERATOR_HH
4#define DUNE_PDELAB_BACKEND_ISTL_VECTORITERATOR_HH
5
6#include <iterator>
7#include <cassert>
8#include <tuple>
9
10#include <dune/pdelab/backend/istl/tags.hh>
11
12namespace Dune {
13
14 namespace PDELab {
15
16 namespace ISTL {
17
18 namespace impl {
19
20 template<typename T, bool is_const, typename Tag, typename... Iterators>
21 struct _extract_iterators;
22
23 template<typename T, typename... Iterators>
24 struct _extract_iterators<T,true,tags::block_vector,Iterators...>
25 : public _extract_iterators<typename T::block_type,
26 true,
27 typename tags::container<typename T::block_type>::type::base_tag,
28 Iterators..., typename T::const_iterator
29 >
30 {};
31
32 template<typename T, typename... Iterators>
33 struct _extract_iterators<T,false,tags::block_vector,Iterators...>
34 : public _extract_iterators<typename T::block_type,
35 false,
36 typename tags::container<typename T::block_type>::type::base_tag,
37 Iterators..., typename T::iterator
38 >
39 {};
40
41 template<typename T, typename... Iterators>
42 struct _extract_iterators<T,true,tags::field_vector,Iterators...>
43 {
44 typedef std::tuple<Iterators...,typename T::const_iterator> type;
45 };
46
47 template<typename T, typename... Iterators>
48 struct _extract_iterators<T,false,tags::field_vector,Iterators...>
49 {
50 typedef std::tuple<Iterators...,typename T::iterator> type;
51 };
52
53
54 template<typename T, typename... Iterators>
55 struct _extract_iterators<T,true,tags::dynamic_vector,Iterators...>
56 {
57 typedef std::tuple<Iterators...,typename T::const_iterator> type;
58 };
59
60 template<typename T, typename... Iterators>
61 struct _extract_iterators<T,false,tags::dynamic_vector,Iterators...>
62 {
63 typedef std::tuple<Iterators...,typename T::iterator> type;
64 };
65
66
67 template<typename V>
68 struct extract_iterators
69 : public _extract_iterators<V,false,typename tags::container<V>::type::base_tag>
70 {};
71
72 template<typename V>
73 struct extract_iterators<const V>
74 : public _extract_iterators<V,true,typename tags::container<V>::type::base_tag>
75 {};
76
77
78 template<typename V>
79 struct vector_iterator_base
80 {
81 typedef V vector;
82 typedef V& vector_reference;
83 typedef typename tags::container<V>::type::base_tag vector_tag;
84 static const bool is_const = false;
85 using iterator_category = std::forward_iterator_tag;
86 using value_type = typename V::field_type;
87 using difference_type = typename std::ptrdiff_t;
88 using pointer = typename V::field_type*;
89 using reference = typename V::field_type&;
90 };
91
92 template<typename V>
93 struct vector_iterator_base<const V>
94 {
95 typedef V vector;
96 typedef const V& vector_reference;
97 typedef typename tags::container<V>::type::base_tag vector_tag;
98 static const bool is_const = true;
99 using iterator_category = std::forward_iterator_tag;
100 using value_type = typename V::field_type;
101 using difference_type = typename std::ptrdiff_t;
102 using pointer = const typename V::field_type*;
103 using reference = const typename V::field_type&;
104 };
105
106 }
107
108 template<typename V>
109 class vector_iterator
110 : public impl::vector_iterator_base<V>
111 {
112
113 typedef impl::vector_iterator_base<V> BaseT;
114 typedef typename BaseT::vector vector;
115 typedef typename BaseT::vector_reference vector_reference;
116 typedef typename BaseT::vector_tag vector_tag;
117 typedef typename impl::extract_iterators<V>::type Iterators;
118 static const bool is_const = BaseT::is_const;
119
120 template<typename>
121 friend class vector_iterator;
122
123 public:
124
125 vector_iterator(vector_reference vector, bool at_end)
126 : _at_end(at_end)
127 , _current(nullptr)
128 {
129 if (!_at_end)
130 if (!start(vector_tag(),level<0>(),vector))
131 _at_end = true;
132 }
133
134
135 // Copy constructor from iterator to const_iterator
136 // We disable this one if the two types are identical to avoid hiding
137 // the default copy constructor
138 template<typename W>
139 vector_iterator(const vector_iterator<W>& r, typename std::enable_if<is_const && !std::is_same<V,W>::value && std::is_same<vector,W>::value,void*>::type = nullptr)
140 : _at_end(r._at_end)
141 , _current(r._current)
142 , _iterators(r._iterators)
143 , _end(r._end)
144 {}
145
146
147 // Assignment operator from iterator to const_iterator
148 // We disable this one if the two types are identical to avoid hiding
149 // the default assignment operator
150 template<typename W>
151 typename std::enable_if<
152 is_const && !std::is_same<vector,W>::value && std::is_same<vector,W>::value,
153 vector_iterator&
154 >::type
155 operator=(const vector_iterator<W>& r)
156 {
157 _at_end = r._at_end;
158 _current =r._current;
159 _iterators = r._iterators;
160 _end = r._end;
161 return *this;
162 }
163
164
165 typename BaseT::pointer operator->() const
166 {
167 assert(!_at_end);
168 return _current;
169 }
170
171 typename BaseT::reference operator*() const
172 {
173 assert(!_at_end);
174 return *_current;
175 }
176
177 vector_iterator& operator++()
178 {
179 increment();
180 return *this;
181 }
182
183 vector_iterator operator++(int)
184 {
185 vector_iterator tmp(*this);
186 increment();
187 return tmp;
188 }
189
190 template<typename W>
191 typename std::enable_if<
192 std::is_same<vector,typename vector_iterator<W>::vector>::value,
193 bool
194 >::type
195 operator==(const vector_iterator<W>& r) const
196 {
197 if (!_at_end)
198 {
199 if (r._at_end)
200 return false;
201 return _current == r._current;
202 }
203 else
204 return r._at_end;
205 }
206
207 template<typename W>
208 typename std::enable_if<
209 std::is_same<vector,typename vector_iterator<W>::vector>::value,
210 bool
211 >::type
212 operator!=(const vector_iterator<W>& r) const
213 {
214 return !operator==(r);
215 }
216
217 private:
218
219 template<std::size_t l>
220 struct level
221 : public std::integral_constant<std::size_t,l>
222 {};
223
224 void increment()
225 {
226 assert(!_at_end);
227 if (!advance(vector_tag(),level<0>()))
228 _at_end = true;
229 }
230
231 template<std::size_t l, typename Block>
232 bool start_leaf(level<l>, Block& block)
233 {
234 typedef typename std::tuple_element<l,Iterators>::type iterator;
235 iterator& it = std::get<l>(_iterators);
236 iterator& end = std::get<l>(_end);
237
238 it = block.begin();
239 end = block.end();
240
241 if (it == end)
242 return false;
243
244 _current = &(*it);
245
246 return true;
247 }
248
249 template<std::size_t l, typename Block>
250 bool start(tags::field_vector_n, level<l>, Block& block)
251 {
252 return start_leaf(level<l>(),block);
253 }
254
255 template<std::size_t l, typename Block>
256 bool start(tags::dynamic_vector, level<l>, Block& block)
257 {
258 return start_leaf(level<l>(),block);
259 }
260
261 template<std::size_t l, typename Block>
262 bool start(tags::field_vector_1, level<l>, Block& block)
263 {
264 _current = &(block[0]);
265 return true;
266 }
267
268
269 template<std::size_t l, typename Block>
270 bool start(tags::block_vector, level<l>, Block& block)
271 {
272 typedef typename std::tuple_element<l,Iterators>::type iterator;
273 iterator& it = std::get<l>(_iterators);
274 iterator& end = std::get<l>(_end);
275
276 it = block.begin();
277 end = block.end();
278
279 while (it != end)
280 {
281 if (start(container_tag(*it),level<l+1>(),*it))
282 return true;
283
284 ++it;
285 }
286
287 return false;
288 }
289
290
291 template<std::size_t l>
292 bool advance_leaf(level<l>)
293 {
294 typedef typename std::tuple_element<l,Iterators>::type iterator;
295 iterator& it = std::get<l>(_iterators);
296 const iterator& end = std::get<l>(_end);
297
298 ++it;
299
300 if (it == end)
301 return false;
302
303 _current = &(*it);
304
305 return true;
306 }
307
308 template<std::size_t l>
309 bool advance(tags::field_vector_n, level<l>)
310 {
311 return advance_leaf(level<l>());
312 }
313
314 template<std::size_t l>
315 bool advance(tags::dynamic_vector, level<l>)
316 {
317 return advance_leaf(level<l>());
318 }
319
320 template<std::size_t l>
321 bool advance(tags::field_vector_1, level<l>)
322 {
323 return false;
324 }
325
326
327 template<std::size_t l>
328 bool advance(tags::block_vector, level<l>)
329 {
330 typedef typename std::tuple_element<l,Iterators>::type iterator;
331 iterator& it = std::get<l>(_iterators);
332 iterator& end = std::get<l>(_end);
333
334 if (advance(container_tag(*it),level<l+1>()))
335 return true;
336
337 ++it;
338
339 while (it != end)
340 {
341 if (start(container_tag(*it),level<l+1>(),*it))
342 return true;
343
344 ++it;
345 }
346
347 return false;
348 }
349
350
351 bool _at_end;
352 typename BaseT::pointer _current;
353 Iterators _iterators;
354 Iterators _end;
355
356 };
357
358 } // namespace ISTL
359 } // namespace PDELab
360} // namespace Dune
361
362
363
364#endif // DUNE_PDELAB_BACKEND_ISTL_VECTORITERATOR_HH
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition: iteratorfacades.hh:260
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 24, 23:30, 2024)