Eigen  5.0.1
 
Loading...
Searching...
No Matches
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_STLITERATORS_H
12#define EIGEN_STLITERATORS_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19namespace internal {
20
21template <typename IteratorType>
22struct indexed_based_stl_iterator_traits;
23
24template <typename Derived>
25class indexed_based_stl_iterator_base {
26 protected:
27 using traits = indexed_based_stl_iterator_traits<Derived>;
28 using XprType = typename traits::XprType;
29 using non_const_iterator = indexed_based_stl_iterator_base<typename traits::non_const_iterator>;
30 using const_iterator = indexed_based_stl_iterator_base<typename traits::const_iterator>;
31 using other_iterator = std::conditional_t<std::is_const<XprType>::value, non_const_iterator, const_iterator>;
32
33 friend class indexed_based_stl_iterator_base<typename traits::const_iterator>;
34 friend class indexed_based_stl_iterator_base<typename traits::non_const_iterator>;
35
36 public:
37 using difference_type = Index;
38 using iterator_category = std::random_access_iterator_tag;
39
40 indexed_based_stl_iterator_base() noexcept = default;
41 indexed_based_stl_iterator_base(XprType& xpr, Index index) noexcept : mp_xpr(&xpr), m_index(index) {}
42
43 indexed_based_stl_iterator_base(const non_const_iterator& other) noexcept
44 : mp_xpr(other.mp_xpr), m_index(other.m_index) {}
45
46 indexed_based_stl_iterator_base& operator=(const non_const_iterator& other) {
47 mp_xpr = other.mp_xpr;
48 m_index = other.m_index;
49 return *this;
50 }
51
52 Derived& operator++() {
53 ++m_index;
54 return derived();
55 }
56 Derived& operator--() {
57 --m_index;
58 return derived();
59 }
60
61 Derived operator++(int) {
62 Derived prev(derived());
63 operator++();
64 return prev;
65 }
66 Derived operator--(int) {
67 Derived prev(derived());
68 operator--();
69 return prev;
70 }
71
72 friend Derived operator+(const indexed_based_stl_iterator_base& a, Index b) {
73 Derived ret(a.derived());
74 ret += b;
75 return ret;
76 }
77 friend Derived operator-(const indexed_based_stl_iterator_base& a, Index b) {
78 Derived ret(a.derived());
79 ret -= b;
80 return ret;
81 }
82 friend Derived operator+(Index a, const indexed_based_stl_iterator_base& b) {
83 Derived ret(b.derived());
84 ret += a;
85 return ret;
86 }
87 friend Derived operator-(Index a, const indexed_based_stl_iterator_base& b) {
88 Derived ret(b.derived());
89 ret -= a;
90 return ret;
91 }
92
93 Derived& operator+=(Index b) {
94 m_index += b;
95 return derived();
96 }
97 Derived& operator-=(Index b) {
98 m_index -= b;
99 return derived();
100 }
101
102 difference_type operator-(const indexed_based_stl_iterator_base& other) const {
103 eigen_assert(mp_xpr == other.mp_xpr);
104 return m_index - other.m_index;
105 }
106
107 difference_type operator-(const other_iterator& other) const {
108 eigen_assert(mp_xpr == other.mp_xpr);
109 return m_index - other.m_index;
110 }
111
112 bool operator==(const indexed_based_stl_iterator_base& other) const {
113 eigen_assert(mp_xpr == other.mp_xpr);
114 return m_index == other.m_index;
115 }
116 bool operator!=(const indexed_based_stl_iterator_base& other) const {
117 eigen_assert(mp_xpr == other.mp_xpr);
118 return m_index != other.m_index;
119 }
120 bool operator<(const indexed_based_stl_iterator_base& other) const {
121 eigen_assert(mp_xpr == other.mp_xpr);
122 return m_index < other.m_index;
123 }
124 bool operator<=(const indexed_based_stl_iterator_base& other) const {
125 eigen_assert(mp_xpr == other.mp_xpr);
126 return m_index <= other.m_index;
127 }
128 bool operator>(const indexed_based_stl_iterator_base& other) const {
129 eigen_assert(mp_xpr == other.mp_xpr);
130 return m_index > other.m_index;
131 }
132 bool operator>=(const indexed_based_stl_iterator_base& other) const {
133 eigen_assert(mp_xpr == other.mp_xpr);
134 return m_index >= other.m_index;
135 }
136
137 bool operator==(const other_iterator& other) const {
138 eigen_assert(mp_xpr == other.mp_xpr);
139 return m_index == other.m_index;
140 }
141 bool operator!=(const other_iterator& other) const {
142 eigen_assert(mp_xpr == other.mp_xpr);
143 return m_index != other.m_index;
144 }
145 bool operator<(const other_iterator& other) const {
146 eigen_assert(mp_xpr == other.mp_xpr);
147 return m_index < other.m_index;
148 }
149 bool operator<=(const other_iterator& other) const {
150 eigen_assert(mp_xpr == other.mp_xpr);
151 return m_index <= other.m_index;
152 }
153 bool operator>(const other_iterator& other) const {
154 eigen_assert(mp_xpr == other.mp_xpr);
155 return m_index > other.m_index;
156 }
157 bool operator>=(const other_iterator& other) const {
158 eigen_assert(mp_xpr == other.mp_xpr);
159 return m_index >= other.m_index;
160 }
161
162 protected:
163 Derived& derived() { return static_cast<Derived&>(*this); }
164 const Derived& derived() const { return static_cast<const Derived&>(*this); }
165
166 XprType* mp_xpr = nullptr;
167 Index m_index = 0;
168};
169
170template <typename Derived>
171class indexed_based_stl_reverse_iterator_base {
172 protected:
173 using traits = indexed_based_stl_iterator_traits<Derived>;
174 using XprType = typename traits::XprType;
175 using non_const_iterator = indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator>;
176 using const_iterator = indexed_based_stl_reverse_iterator_base<typename traits::const_iterator>;
177 using other_iterator = std::conditional_t<std::is_const<XprType>::value, non_const_iterator, const_iterator>;
178
179 friend class indexed_based_stl_reverse_iterator_base<typename traits::const_iterator>;
180 friend class indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator>;
181
182 public:
183 using difference_type = Index;
184 using iterator_category = std::random_access_iterator_tag;
185
186 indexed_based_stl_reverse_iterator_base() = default;
187 indexed_based_stl_reverse_iterator_base(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {}
188
189 indexed_based_stl_reverse_iterator_base(const non_const_iterator& other)
190 : mp_xpr(other.mp_xpr), m_index(other.m_index) {}
191
192 indexed_based_stl_reverse_iterator_base& operator=(const non_const_iterator& other) {
193 mp_xpr = other.mp_xpr;
194 m_index = other.m_index;
195 return *this;
196 }
197
198 Derived& operator++() {
199 --m_index;
200 return derived();
201 }
202 Derived& operator--() {
203 ++m_index;
204 return derived();
205 }
206
207 Derived operator++(int) {
208 Derived prev(derived());
209 operator++();
210 return prev;
211 }
212 Derived operator--(int) {
213 Derived prev(derived());
214 operator--();
215 return prev;
216 }
217
218 friend Derived operator+(const indexed_based_stl_reverse_iterator_base& a, Index b) {
219 Derived ret(a.derived());
220 ret += b;
221 return ret;
222 }
223 friend Derived operator-(const indexed_based_stl_reverse_iterator_base& a, Index b) {
224 Derived ret(a.derived());
225 ret -= b;
226 return ret;
227 }
228 friend Derived operator+(Index a, const indexed_based_stl_reverse_iterator_base& b) {
229 Derived ret(b.derived());
230 ret += a;
231 return ret;
232 }
233 friend Derived operator-(Index a, const indexed_based_stl_reverse_iterator_base& b) {
234 Derived ret(b.derived());
235 ret -= a;
236 return ret;
237 }
238
239 Derived& operator+=(Index b) {
240 m_index -= b;
241 return derived();
242 }
243 Derived& operator-=(Index b) {
244 m_index += b;
245 return derived();
246 }
247
248 difference_type operator-(const indexed_based_stl_reverse_iterator_base& other) const {
249 eigen_assert(mp_xpr == other.mp_xpr);
250 return other.m_index - m_index;
251 }
252
253 difference_type operator-(const other_iterator& other) const {
254 eigen_assert(mp_xpr == other.mp_xpr);
255 return other.m_index - m_index;
256 }
257
258 bool operator==(const indexed_based_stl_reverse_iterator_base& other) const {
259 eigen_assert(mp_xpr == other.mp_xpr);
260 return m_index == other.m_index;
261 }
262 bool operator!=(const indexed_based_stl_reverse_iterator_base& other) const {
263 eigen_assert(mp_xpr == other.mp_xpr);
264 return m_index != other.m_index;
265 }
266 bool operator<(const indexed_based_stl_reverse_iterator_base& other) const {
267 eigen_assert(mp_xpr == other.mp_xpr);
268 return m_index > other.m_index;
269 }
270 bool operator<=(const indexed_based_stl_reverse_iterator_base& other) const {
271 eigen_assert(mp_xpr == other.mp_xpr);
272 return m_index >= other.m_index;
273 }
274 bool operator>(const indexed_based_stl_reverse_iterator_base& other) const {
275 eigen_assert(mp_xpr == other.mp_xpr);
276 return m_index < other.m_index;
277 }
278 bool operator>=(const indexed_based_stl_reverse_iterator_base& other) const {
279 eigen_assert(mp_xpr == other.mp_xpr);
280 return m_index <= other.m_index;
281 }
282
283 bool operator==(const other_iterator& other) const {
284 eigen_assert(mp_xpr == other.mp_xpr);
285 return m_index == other.m_index;
286 }
287 bool operator!=(const other_iterator& other) const {
288 eigen_assert(mp_xpr == other.mp_xpr);
289 return m_index != other.m_index;
290 }
291 bool operator<(const other_iterator& other) const {
292 eigen_assert(mp_xpr == other.mp_xpr);
293 return m_index > other.m_index;
294 }
295 bool operator<=(const other_iterator& other) const {
296 eigen_assert(mp_xpr == other.mp_xpr);
297 return m_index >= other.m_index;
298 }
299 bool operator>(const other_iterator& other) const {
300 eigen_assert(mp_xpr == other.mp_xpr);
301 return m_index < other.m_index;
302 }
303 bool operator>=(const other_iterator& other) const {
304 eigen_assert(mp_xpr == other.mp_xpr);
305 return m_index <= other.m_index;
306 }
307
308 protected:
309 Derived& derived() { return static_cast<Derived&>(*this); }
310 const Derived& derived() const { return static_cast<const Derived&>(*this); }
311
312 XprType* mp_xpr = nullptr;
313 Index m_index = 0;
314};
315
316template <typename XprType>
317class pointer_based_stl_iterator {
318 enum { is_lvalue = internal::is_lvalue<XprType>::value };
319 using non_const_iterator = pointer_based_stl_iterator<std::remove_const_t<XprType>>;
320 using const_iterator = pointer_based_stl_iterator<std::add_const_t<XprType>>;
321 using other_iterator = std::conditional_t<std::is_const<XprType>::value, non_const_iterator, const_iterator>;
322
323 friend class pointer_based_stl_iterator<std::add_const_t<XprType>>;
324 friend class pointer_based_stl_iterator<std::remove_const_t<XprType>>;
325
326 public:
327 using difference_type = Index;
328 using value_type = typename XprType::Scalar;
329#if EIGEN_COMP_CXXVER >= 20 && defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L
330 using iterator_category = std::conditional_t<XprType::InnerStrideAtCompileTime == 1, std::contiguous_iterator_tag,
331 std::random_access_iterator_tag>;
332#else
333 using iterator_category = std::random_access_iterator_tag;
334#endif
335 using pointer = std::conditional_t<bool(is_lvalue), value_type*, const value_type*>;
336 using reference = std::conditional_t<bool(is_lvalue), value_type&, const value_type&>;
337
338 pointer_based_stl_iterator() noexcept = default;
339 pointer_based_stl_iterator(XprType& xpr, Index index) noexcept
340 : m_ptr(xpr.data() + index * xpr.innerStride()), m_incr(xpr.innerStride()) {}
341
342 pointer_based_stl_iterator(const non_const_iterator& other) noexcept : m_ptr(other.m_ptr), m_incr(other.m_incr) {}
343
344 pointer_based_stl_iterator& operator=(const non_const_iterator& other) noexcept {
345 m_ptr = other.m_ptr;
346 m_incr.setValue(other.m_incr);
347 return *this;
348 }
349
350 reference operator*() const { return *m_ptr; }
351 reference operator[](Index i) const { return *(m_ptr + i * m_incr.value()); }
352 pointer operator->() const { return m_ptr; }
353
354 pointer_based_stl_iterator& operator++() {
355 m_ptr += m_incr.value();
356 return *this;
357 }
358 pointer_based_stl_iterator& operator--() {
359 m_ptr -= m_incr.value();
360 return *this;
361 }
362
363 pointer_based_stl_iterator operator++(int) {
364 pointer_based_stl_iterator prev(*this);
365 operator++();
366 return prev;
367 }
368 pointer_based_stl_iterator operator--(int) {
369 pointer_based_stl_iterator prev(*this);
370 operator--();
371 return prev;
372 }
373
374 friend pointer_based_stl_iterator operator+(const pointer_based_stl_iterator& a, Index b) {
375 pointer_based_stl_iterator ret(a);
376 ret += b;
377 return ret;
378 }
379 friend pointer_based_stl_iterator operator-(const pointer_based_stl_iterator& a, Index b) {
380 pointer_based_stl_iterator ret(a);
381 ret -= b;
382 return ret;
383 }
384 friend pointer_based_stl_iterator operator+(Index a, const pointer_based_stl_iterator& b) {
385 pointer_based_stl_iterator ret(b);
386 ret += a;
387 return ret;
388 }
389 friend pointer_based_stl_iterator operator-(Index a, const pointer_based_stl_iterator& b) {
390 pointer_based_stl_iterator ret(b);
391 ret -= a;
392 return ret;
393 }
394
395 pointer_based_stl_iterator& operator+=(Index b) {
396 m_ptr += b * m_incr.value();
397 return *this;
398 }
399 pointer_based_stl_iterator& operator-=(Index b) {
400 m_ptr -= b * m_incr.value();
401 return *this;
402 }
403
404 difference_type operator-(const pointer_based_stl_iterator& other) const {
405 return (m_ptr - other.m_ptr) / m_incr.value();
406 }
407
408 difference_type operator-(const other_iterator& other) const { return (m_ptr - other.m_ptr) / m_incr.value(); }
409
410 bool operator==(const pointer_based_stl_iterator& other) const { return m_ptr == other.m_ptr; }
411 bool operator!=(const pointer_based_stl_iterator& other) const { return m_ptr != other.m_ptr; }
412 bool operator<(const pointer_based_stl_iterator& other) const {
413 // Iterator order follows the stride, not necessarily increasing addresses.
414 return m_incr.value() < 0 ? m_ptr > other.m_ptr : m_ptr < other.m_ptr;
415 }
416 bool operator<=(const pointer_based_stl_iterator& other) const { return !(other < *this); }
417 bool operator>(const pointer_based_stl_iterator& other) const { return other < *this; }
418 bool operator>=(const pointer_based_stl_iterator& other) const { return !(*this < other); }
419
420 bool operator==(const other_iterator& other) const { return m_ptr == other.m_ptr; }
421 bool operator!=(const other_iterator& other) const { return m_ptr != other.m_ptr; }
422 bool operator<(const other_iterator& other) const {
423 return m_incr.value() < 0 ? m_ptr > other.m_ptr : m_ptr < other.m_ptr;
424 }
425 bool operator<=(const other_iterator& other) const { return !(other < *this); }
426 bool operator>(const other_iterator& other) const { return other < *this; }
427 bool operator>=(const other_iterator& other) const { return !(*this < other); }
428
429 protected:
430 pointer m_ptr = nullptr;
431 internal::variable_if_dynamic<Index, XprType::InnerStrideAtCompileTime> m_incr{XprType::InnerStrideAtCompileTime};
432};
433
434template <typename XprType_>
435struct indexed_based_stl_iterator_traits<generic_randaccess_stl_iterator<XprType_>> {
436 using XprType = XprType_;
437 using non_const_iterator = generic_randaccess_stl_iterator<std::remove_const_t<XprType>>;
438 using const_iterator = generic_randaccess_stl_iterator<std::add_const_t<XprType>>;
439};
440
441template <typename XprType>
442class generic_randaccess_stl_iterator
443 : public indexed_based_stl_iterator_base<generic_randaccess_stl_iterator<XprType>> {
444 public:
445 using value_type = typename XprType::Scalar;
446
447 protected:
448 enum {
449 has_direct_access = (internal::traits<XprType>::Flags & DirectAccessBit) ? 1 : 0,
450 is_lvalue = internal::is_lvalue<XprType>::value
451 };
452
453 using Base = indexed_based_stl_iterator_base<generic_randaccess_stl_iterator>;
454 using Base::m_index;
455 using Base::mp_xpr;
456
457 // TODO: currently const Transpose/Reshape expressions never returns const references,
458 // so lets return by value too.
459 // typedef std::conditional_t<bool(has_direct_access), const value_type&, const value_type> read_only_ref_t;
460 using read_only_ref_t = const value_type;
461
462 public:
463 using pointer = std::conditional_t<bool(is_lvalue), value_type*, const value_type*>;
464 using reference = std::conditional_t<bool(is_lvalue), value_type&, read_only_ref_t>;
465
466 generic_randaccess_stl_iterator() = default;
467 generic_randaccess_stl_iterator(XprType& xpr, Index index) : Base(xpr, index) {}
468 generic_randaccess_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {}
469 using Base::operator=;
470
471 reference operator*() const { return (*mp_xpr)(m_index); }
472 reference operator[](Index i) const { return (*mp_xpr)(m_index + i); }
473 pointer operator->() const { return &((*mp_xpr)(m_index)); }
474};
475
476template <typename XprType_, DirectionType Direction>
477struct indexed_based_stl_iterator_traits<subvector_stl_iterator<XprType_, Direction>> {
478 using XprType = XprType_;
479 using non_const_iterator = subvector_stl_iterator<std::remove_const_t<XprType>, Direction>;
480 using const_iterator = subvector_stl_iterator<std::add_const_t<XprType>, Direction>;
481};
482
483template <typename XprType, DirectionType Direction>
484class subvector_stl_iterator : public indexed_based_stl_iterator_base<subvector_stl_iterator<XprType, Direction>> {
485 protected:
486 enum { is_lvalue = internal::is_lvalue<XprType>::value };
487
488 using Base = indexed_based_stl_iterator_base<subvector_stl_iterator>;
489 using Base::m_index;
490 using Base::mp_xpr;
491
492 using SubVectorType = std::conditional_t<Direction == Vertical, typename XprType::ColXpr, typename XprType::RowXpr>;
493 using ConstSubVectorType =
494 std::conditional_t<Direction == Vertical, typename XprType::ConstColXpr, typename XprType::ConstRowXpr>;
495
496 public:
497 using reference = std::conditional_t<bool(is_lvalue), SubVectorType, ConstSubVectorType>;
498 using value_type = typename reference::PlainObject;
499
500 private:
501 class subvector_stl_iterator_ptr {
502 public:
503 subvector_stl_iterator_ptr(const reference& subvector) : m_subvector(subvector) {}
504 reference* operator->() { return &m_subvector; }
505
506 private:
507 reference m_subvector;
508 };
509
510 public:
511 using pointer = subvector_stl_iterator_ptr;
512
513 subvector_stl_iterator() = default;
514 subvector_stl_iterator(XprType& xpr, Index index) : Base(xpr, index) {}
515 subvector_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {}
516
517 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); }
518 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index + i); }
519 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); }
520};
521
522template <typename XprType_, DirectionType Direction>
523struct indexed_based_stl_iterator_traits<subvector_stl_reverse_iterator<XprType_, Direction>> {
524 using XprType = XprType_;
525 using non_const_iterator = subvector_stl_reverse_iterator<std::remove_const_t<XprType>, Direction>;
526 using const_iterator = subvector_stl_reverse_iterator<std::add_const_t<XprType>, Direction>;
527};
528
529template <typename XprType, DirectionType Direction>
530class subvector_stl_reverse_iterator
531 : public indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator<XprType, Direction>> {
532 protected:
533 enum { is_lvalue = internal::is_lvalue<XprType>::value };
534
535 using Base = indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator>;
536 using Base::m_index;
537 using Base::mp_xpr;
538
539 using SubVectorType = std::conditional_t<Direction == Vertical, typename XprType::ColXpr, typename XprType::RowXpr>;
540 using ConstSubVectorType =
541 std::conditional_t<Direction == Vertical, typename XprType::ConstColXpr, typename XprType::ConstRowXpr>;
542
543 public:
544 using reference = std::conditional_t<bool(is_lvalue), SubVectorType, ConstSubVectorType>;
545 using value_type = typename reference::PlainObject;
546
547 private:
548 class subvector_stl_reverse_iterator_ptr {
549 public:
550 subvector_stl_reverse_iterator_ptr(const reference& subvector) : m_subvector(subvector) {}
551 reference* operator->() { return &m_subvector; }
552
553 private:
554 reference m_subvector;
555 };
556
557 public:
558 using pointer = subvector_stl_reverse_iterator_ptr;
559
560 subvector_stl_reverse_iterator() = default;
561 subvector_stl_reverse_iterator(XprType& xpr, Index index) : Base(xpr, index) {}
562 subvector_stl_reverse_iterator(const typename Base::non_const_iterator& other) : Base(other) {}
563
564 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); }
565 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index - i); }
566 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); }
567};
568
569} // namespace internal
570
575template <typename Derived>
577 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
578 return iterator(derived(), 0);
579}
581/** const version of begin() */
582template <typename Derived>
584 return cbegin();
586
591template <typename Derived>
593 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
594 return const_iterator(derived(), 0);
595}
596
601template <typename Derived>
603 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
604 return iterator(derived(), size());
605}
606
608template <typename Derived>
610 return cend();
611}
612
617template <typename Derived>
619 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
620 return const_iterator(derived(), size());
621}
622
623} // namespace Eigen
624
625#endif // EIGEN_STLITERATORS_H
random_access_iterator_type const_iterator
Definition DenseBase.h:563
iterator begin()
Definition StlIterators.h:576
iterator end()
Definition StlIterators.h:602
const_iterator cbegin() const
Definition StlIterators.h:592
const_iterator cend() const
Definition StlIterators.h:618
random_access_iterator_type iterator
Definition DenseBase.h:561
constexpr unsigned int DirectAccessBit
Definition Constants.h:160