Eigen  3.4.90 (git rev a4098ac676528a83cfb73d4d26ce1b42ec05f47c)
StlIterators.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2018 Gael Guennebaud <gael.guennebaud@inria.fr>
5//
6// This Source Code Form is subject to the terms of the Mozilla
7// Public License v. 2.0. If a copy of the MPL was not distributed
8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#ifndef EIGEN_STLITERATORS_H
11#define EIGEN_STLITERATORS_H
12
13#include "./InternalHeaderCheck.h"
14
15namespace Eigen {
16
17namespace internal {
18
19template<typename IteratorType>
20struct indexed_based_stl_iterator_traits;
21
22template<typename Derived>
23class indexed_based_stl_iterator_base
24{
25protected:
26 typedef indexed_based_stl_iterator_traits<Derived> traits;
27 typedef typename traits::XprType XprType;
28 typedef indexed_based_stl_iterator_base<typename traits::non_const_iterator> non_const_iterator;
29 typedef indexed_based_stl_iterator_base<typename traits::const_iterator> const_iterator;
30 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator;
31 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class:
32 friend class indexed_based_stl_iterator_base<typename traits::const_iterator>;
33 friend class indexed_based_stl_iterator_base<typename traits::non_const_iterator>;
34public:
35 typedef Index difference_type;
36 typedef std::random_access_iterator_tag iterator_category;
37
38 indexed_based_stl_iterator_base() EIGEN_NO_THROW : mp_xpr(0), m_index(0) {}
39 indexed_based_stl_iterator_base(XprType& xpr, Index index) EIGEN_NO_THROW : mp_xpr(&xpr), m_index(index) {}
40
41 indexed_based_stl_iterator_base(const non_const_iterator& other) EIGEN_NO_THROW
42 : mp_xpr(other.mp_xpr), m_index(other.m_index)
43 {}
44
45 indexed_based_stl_iterator_base& operator=(const non_const_iterator& other)
46 {
47 mp_xpr = other.mp_xpr;
48 m_index = other.m_index;
49 return *this;
50 }
51
52 Derived& operator++() { ++m_index; return derived(); }
53 Derived& operator--() { --m_index; return derived(); }
54
55 Derived operator++(int) { Derived prev(derived()); operator++(); return prev;}
56 Derived operator--(int) { Derived prev(derived()); operator--(); return prev;}
57
58 friend Derived operator+(const indexed_based_stl_iterator_base& a, Index b) { Derived ret(a.derived()); ret += b; return ret; }
59 friend Derived operator-(const indexed_based_stl_iterator_base& a, Index b) { Derived ret(a.derived()); ret -= b; return ret; }
60 friend Derived operator+(Index a, const indexed_based_stl_iterator_base& b) { Derived ret(b.derived()); ret += a; return ret; }
61 friend Derived operator-(Index a, const indexed_based_stl_iterator_base& b) { Derived ret(b.derived()); ret -= a; return ret; }
62
63 Derived& operator+=(Index b) { m_index += b; return derived(); }
64 Derived& operator-=(Index b) { m_index -= b; return derived(); }
65
66 difference_type operator-(const indexed_based_stl_iterator_base& other) const
67 {
68 eigen_assert(mp_xpr == other.mp_xpr);
69 return m_index - other.m_index;
70 }
71
72 difference_type operator-(const other_iterator& other) const
73 {
74 eigen_assert(mp_xpr == other.mp_xpr);
75 return m_index - other.m_index;
76 }
77
78 bool operator==(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; }
79 bool operator!=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; }
80 bool operator< (const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; }
81 bool operator<=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; }
82 bool operator> (const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; }
83 bool operator>=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; }
84
85 bool operator==(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; }
86 bool operator!=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; }
87 bool operator< (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; }
88 bool operator<=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; }
89 bool operator> (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; }
90 bool operator>=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; }
91
92protected:
93
94 Derived& derived() { return static_cast<Derived&>(*this); }
95 const Derived& derived() const { return static_cast<const Derived&>(*this); }
96
97 XprType *mp_xpr;
98 Index m_index;
99};
100
101template<typename Derived>
102class indexed_based_stl_reverse_iterator_base
103{
104protected:
105 typedef indexed_based_stl_iterator_traits<Derived> traits;
106 typedef typename traits::XprType XprType;
107 typedef indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator> non_const_iterator;
108 typedef indexed_based_stl_reverse_iterator_base<typename traits::const_iterator> const_iterator;
109 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator;
110 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class:
111 friend class indexed_based_stl_reverse_iterator_base<typename traits::const_iterator>;
112 friend class indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator>;
113public:
114 typedef Index difference_type;
115 typedef std::random_access_iterator_tag iterator_category;
116
117 indexed_based_stl_reverse_iterator_base() : mp_xpr(0), m_index(0) {}
118 indexed_based_stl_reverse_iterator_base(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {}
119
120 indexed_based_stl_reverse_iterator_base(const non_const_iterator& other)
121 : mp_xpr(other.mp_xpr), m_index(other.m_index)
122 {}
123
124 indexed_based_stl_reverse_iterator_base& operator=(const non_const_iterator& other)
125 {
126 mp_xpr = other.mp_xpr;
127 m_index = other.m_index;
128 return *this;
129 }
130
131 Derived& operator++() { --m_index; return derived(); }
132 Derived& operator--() { ++m_index; return derived(); }
133
134 Derived operator++(int) { Derived prev(derived()); operator++(); return prev;}
135 Derived operator--(int) { Derived prev(derived()); operator--(); return prev;}
136
137 friend Derived operator+(const indexed_based_stl_reverse_iterator_base& a, Index b) { Derived ret(a.derived()); ret += b; return ret; }
138 friend Derived operator-(const indexed_based_stl_reverse_iterator_base& a, Index b) { Derived ret(a.derived()); ret -= b; return ret; }
139 friend Derived operator+(Index a, const indexed_based_stl_reverse_iterator_base& b) { Derived ret(b.derived()); ret += a; return ret; }
140 friend Derived operator-(Index a, const indexed_based_stl_reverse_iterator_base& b) { Derived ret(b.derived()); ret -= a; return ret; }
141
142 Derived& operator+=(Index b) { m_index -= b; return derived(); }
143 Derived& operator-=(Index b) { m_index += b; return derived(); }
144
145 difference_type operator-(const indexed_based_stl_reverse_iterator_base& other) const
146 {
147 eigen_assert(mp_xpr == other.mp_xpr);
148 return other.m_index - m_index;
149 }
150
151 difference_type operator-(const other_iterator& other) const
152 {
153 eigen_assert(mp_xpr == other.mp_xpr);
154 return other.m_index - m_index;
155 }
156
157 bool operator==(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; }
158 bool operator!=(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; }
159 bool operator< (const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; }
160 bool operator<=(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; }
161 bool operator> (const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; }
162 bool operator>=(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; }
163
164 bool operator==(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; }
165 bool operator!=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; }
166 bool operator< (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; }
167 bool operator<=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; }
168 bool operator> (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; }
169 bool operator>=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; }
170
171protected:
172
173 Derived& derived() { return static_cast<Derived&>(*this); }
174 const Derived& derived() const { return static_cast<const Derived&>(*this); }
175
176 XprType *mp_xpr;
177 Index m_index;
178};
179
180template<typename XprType>
181class pointer_based_stl_iterator
182{
183 enum { is_lvalue = internal::is_lvalue<XprType>::value };
184 typedef pointer_based_stl_iterator<typename internal::remove_const<XprType>::type> non_const_iterator;
185 typedef pointer_based_stl_iterator<typename internal::add_const<XprType>::type> const_iterator;
186 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator;
187 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class:
188 friend class pointer_based_stl_iterator<typename internal::add_const<XprType>::type>;
189 friend class pointer_based_stl_iterator<typename internal::remove_const<XprType>::type>;
190public:
191 typedef Index difference_type;
192 typedef typename XprType::Scalar value_type;
193 typedef std::random_access_iterator_tag iterator_category;
194 typedef typename internal::conditional<bool(is_lvalue), value_type*, const value_type*>::type pointer;
195 typedef typename internal::conditional<bool(is_lvalue), value_type&, const value_type&>::type reference;
196
197
198 pointer_based_stl_iterator() EIGEN_NO_THROW : m_ptr(0) {}
199 pointer_based_stl_iterator(XprType& xpr, Index index) EIGEN_NO_THROW : m_incr(xpr.innerStride())
200 {
201 m_ptr = xpr.data() + index * m_incr.value();
202 }
203
204 pointer_based_stl_iterator(const non_const_iterator& other) EIGEN_NO_THROW
205 : m_ptr(other.m_ptr), m_incr(other.m_incr)
206 {}
207
208 pointer_based_stl_iterator& operator=(const non_const_iterator& other) EIGEN_NO_THROW
209 {
210 m_ptr = other.m_ptr;
211 m_incr.setValue(other.m_incr);
212 return *this;
213 }
214
215 reference operator*() const { return *m_ptr; }
216 reference operator[](Index i) const { return *(m_ptr+i*m_incr.value()); }
217 pointer operator->() const { return m_ptr; }
218
219 pointer_based_stl_iterator& operator++() { m_ptr += m_incr.value(); return *this; }
220 pointer_based_stl_iterator& operator--() { m_ptr -= m_incr.value(); return *this; }
221
222 pointer_based_stl_iterator operator++(int) { pointer_based_stl_iterator prev(*this); operator++(); return prev;}
223 pointer_based_stl_iterator operator--(int) { pointer_based_stl_iterator prev(*this); operator--(); return prev;}
224
225 friend pointer_based_stl_iterator operator+(const pointer_based_stl_iterator& a, Index b) { pointer_based_stl_iterator ret(a); ret += b; return ret; }
226 friend pointer_based_stl_iterator operator-(const pointer_based_stl_iterator& a, Index b) { pointer_based_stl_iterator ret(a); ret -= b; return ret; }
227 friend pointer_based_stl_iterator operator+(Index a, const pointer_based_stl_iterator& b) { pointer_based_stl_iterator ret(b); ret += a; return ret; }
228 friend pointer_based_stl_iterator operator-(Index a, const pointer_based_stl_iterator& b) { pointer_based_stl_iterator ret(b); ret -= a; return ret; }
229
230 pointer_based_stl_iterator& operator+=(Index b) { m_ptr += b*m_incr.value(); return *this; }
231 pointer_based_stl_iterator& operator-=(Index b) { m_ptr -= b*m_incr.value(); return *this; }
232
233 difference_type operator-(const pointer_based_stl_iterator& other) const {
234 return (m_ptr - other.m_ptr)/m_incr.value();
235 }
236
237 difference_type operator-(const other_iterator& other) const {
238 return (m_ptr - other.m_ptr)/m_incr.value();
239 }
240
241 bool operator==(const pointer_based_stl_iterator& other) const { return m_ptr == other.m_ptr; }
242 bool operator!=(const pointer_based_stl_iterator& other) const { return m_ptr != other.m_ptr; }
243 bool operator< (const pointer_based_stl_iterator& other) const { return m_ptr < other.m_ptr; }
244 bool operator<=(const pointer_based_stl_iterator& other) const { return m_ptr <= other.m_ptr; }
245 bool operator> (const pointer_based_stl_iterator& other) const { return m_ptr > other.m_ptr; }
246 bool operator>=(const pointer_based_stl_iterator& other) const { return m_ptr >= other.m_ptr; }
247
248 bool operator==(const other_iterator& other) const { return m_ptr == other.m_ptr; }
249 bool operator!=(const other_iterator& other) const { return m_ptr != other.m_ptr; }
250 bool operator< (const other_iterator& other) const { return m_ptr < other.m_ptr; }
251 bool operator<=(const other_iterator& other) const { return m_ptr <= other.m_ptr; }
252 bool operator> (const other_iterator& other) const { return m_ptr > other.m_ptr; }
253 bool operator>=(const other_iterator& other) const { return m_ptr >= other.m_ptr; }
254
255protected:
256
257 pointer m_ptr;
258 internal::variable_if_dynamic<Index, XprType::InnerStrideAtCompileTime> m_incr;
259};
260
261template<typename XprType_>
262struct indexed_based_stl_iterator_traits<generic_randaccess_stl_iterator<XprType_> >
263{
264 typedef XprType_ XprType;
265 typedef generic_randaccess_stl_iterator<typename internal::remove_const<XprType>::type> non_const_iterator;
266 typedef generic_randaccess_stl_iterator<typename internal::add_const<XprType>::type> const_iterator;
267};
268
269template<typename XprType>
270class generic_randaccess_stl_iterator : public indexed_based_stl_iterator_base<generic_randaccess_stl_iterator<XprType> >
271{
272public:
273 typedef typename XprType::Scalar value_type;
274
275protected:
276
277 enum {
278 has_direct_access = (internal::traits<XprType>::Flags & DirectAccessBit) ? 1 : 0,
279 is_lvalue = internal::is_lvalue<XprType>::value
280 };
281
282 typedef indexed_based_stl_iterator_base<generic_randaccess_stl_iterator> Base;
283 using Base::m_index;
284 using Base::mp_xpr;
285
286 // TODO currently const Transpose/Reshape expressions never returns const references,
287 // so lets return by value too.
288 //typedef typename internal::conditional<bool(has_direct_access), const value_type&, const value_type>::type read_only_ref_t;
289 typedef const value_type read_only_ref_t;
290
291public:
292
293 typedef typename internal::conditional<bool(is_lvalue), value_type *, const value_type *>::type pointer;
294 typedef typename internal::conditional<bool(is_lvalue), value_type&, read_only_ref_t>::type reference;
295
296 generic_randaccess_stl_iterator() : Base() {}
297 generic_randaccess_stl_iterator(XprType& xpr, Index index) : Base(xpr,index) {}
298 generic_randaccess_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {}
299 using Base::operator=;
300
301 reference operator*() const { return (*mp_xpr)(m_index); }
302 reference operator[](Index i) const { return (*mp_xpr)(m_index+i); }
303 pointer operator->() const { return &((*mp_xpr)(m_index)); }
304};
305
306template<typename XprType_, DirectionType Direction>
307struct indexed_based_stl_iterator_traits<subvector_stl_iterator<XprType_,Direction> >
308{
309 typedef XprType_ XprType;
310 typedef subvector_stl_iterator<typename internal::remove_const<XprType>::type, Direction> non_const_iterator;
311 typedef subvector_stl_iterator<typename internal::add_const<XprType>::type, Direction> const_iterator;
312};
313
314template<typename XprType, DirectionType Direction>
315class subvector_stl_iterator : public indexed_based_stl_iterator_base<subvector_stl_iterator<XprType,Direction> >
316{
317protected:
318
319 enum { is_lvalue = internal::is_lvalue<XprType>::value };
320
321 typedef indexed_based_stl_iterator_base<subvector_stl_iterator> Base;
322 using Base::m_index;
323 using Base::mp_xpr;
324
325 typedef typename internal::conditional<Direction==Vertical,typename XprType::ColXpr,typename XprType::RowXpr>::type SubVectorType;
326 typedef typename internal::conditional<Direction==Vertical,typename XprType::ConstColXpr,typename XprType::ConstRowXpr>::type ConstSubVectorType;
327
328
329public:
330 typedef typename internal::conditional<bool(is_lvalue), SubVectorType, ConstSubVectorType>::type reference;
331 typedef typename reference::PlainObject value_type;
332
333private:
334 class subvector_stl_iterator_ptr
335 {
336 public:
337 subvector_stl_iterator_ptr(const reference &subvector) : m_subvector(subvector) {}
338 reference* operator->() { return &m_subvector; }
339 private:
340 reference m_subvector;
341 };
342public:
343
344 typedef subvector_stl_iterator_ptr pointer;
345
346 subvector_stl_iterator() : Base() {}
347 subvector_stl_iterator(XprType& xpr, Index index) : Base(xpr,index) {}
348
349 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); }
350 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index+i); }
351 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); }
352};
353
354template<typename XprType_, DirectionType Direction>
355struct indexed_based_stl_iterator_traits<subvector_stl_reverse_iterator<XprType_,Direction> >
356{
357 typedef XprType_ XprType;
358 typedef subvector_stl_reverse_iterator<typename internal::remove_const<XprType>::type, Direction> non_const_iterator;
359 typedef subvector_stl_reverse_iterator<typename internal::add_const<XprType>::type, Direction> const_iterator;
360};
361
362template<typename XprType, DirectionType Direction>
363class subvector_stl_reverse_iterator : public indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator<XprType,Direction> >
364{
365protected:
366
367 enum { is_lvalue = internal::is_lvalue<XprType>::value };
368
369 typedef indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator> Base;
370 using Base::m_index;
371 using Base::mp_xpr;
372
373 typedef typename internal::conditional<Direction==Vertical,typename XprType::ColXpr,typename XprType::RowXpr>::type SubVectorType;
374 typedef typename internal::conditional<Direction==Vertical,typename XprType::ConstColXpr,typename XprType::ConstRowXpr>::type ConstSubVectorType;
375
376
377public:
378 typedef typename internal::conditional<bool(is_lvalue), SubVectorType, ConstSubVectorType>::type reference;
379 typedef typename reference::PlainObject value_type;
380
381private:
382 class subvector_stl_reverse_iterator_ptr
383 {
384 public:
385 subvector_stl_reverse_iterator_ptr(const reference &subvector) : m_subvector(subvector) {}
386 reference* operator->() { return &m_subvector; }
387 private:
388 reference m_subvector;
389 };
390public:
391
392 typedef subvector_stl_reverse_iterator_ptr pointer;
393
394 subvector_stl_reverse_iterator() : Base() {}
395 subvector_stl_reverse_iterator(XprType& xpr, Index index) : Base(xpr,index) {}
396
397 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); }
398 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index+i); }
399 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); }
400};
401
402} // namespace internal
403
404
409template<typename Derived>
411{
412 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
413 return iterator(derived(), 0);
414}
415
417template<typename Derived>
419{
420 return cbegin();
421}
422
427template<typename Derived>
429{
430 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
431 return const_iterator(derived(), 0);
432}
433
438template<typename Derived>
440{
441 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
442 return iterator(derived(), size());
443}
444
446template<typename Derived>
448{
449 return cend();
450}
451
456template<typename Derived>
458{
459 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
460 return const_iterator(derived(), size());
461}
462
463} // namespace Eigen
464
465#endif // EIGEN_STLITERATORS_H
random_access_iterator_type const_iterator
Definition: DenseBase.h:612
iterator begin()
Definition: StlIterators.h:410
iterator end()
Definition: StlIterators.h:439
const_iterator cbegin() const
Definition: StlIterators.h:428
const_iterator cend() const
Definition: StlIterators.h:457
random_access_iterator_type iterator
Definition: DenseBase.h:610
const unsigned int DirectAccessBit
Definition: Constants.h:157
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:59
const Product< MatrixDerived, PermutationDerived, AliasFreeProduct > operator*(const MatrixBase< MatrixDerived > &matrix, const PermutationBase< PermutationDerived > &permutation)
Definition: PermutationMatrix.h:517