1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2018 Gael Guennebaud <[email protected]> 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 namespace Eigen { 14 15 namespace internal { 16 17 template<typename IteratorType> 18 struct indexed_based_stl_iterator_traits; 19 20 template<typename Derived> 21 class indexed_based_stl_iterator_base 22 { 23 protected: 24 typedef indexed_based_stl_iterator_traits<Derived> traits; 25 typedef typename traits::XprType XprType; 26 typedef indexed_based_stl_iterator_base<typename traits::non_const_iterator> non_const_iterator; 27 typedef indexed_based_stl_iterator_base<typename traits::const_iterator> const_iterator; 28 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator; 29 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class: 30 friend class indexed_based_stl_iterator_base<typename traits::const_iterator>; 31 friend class indexed_based_stl_iterator_base<typename traits::non_const_iterator>; 32 public: 33 typedef Index difference_type; 34 typedef std::random_access_iterator_tag iterator_category; 35 indexed_based_stl_iterator_base()36 indexed_based_stl_iterator_base() EIGEN_NO_THROW : mp_xpr(0), m_index(0) {} indexed_based_stl_iterator_base(XprType & xpr,Index index)37 indexed_based_stl_iterator_base(XprType& xpr, Index index) EIGEN_NO_THROW : mp_xpr(&xpr), m_index(index) {} 38 indexed_based_stl_iterator_base(const non_const_iterator & other)39 indexed_based_stl_iterator_base(const non_const_iterator& other) EIGEN_NO_THROW 40 : mp_xpr(other.mp_xpr), m_index(other.m_index) 41 {} 42 43 indexed_based_stl_iterator_base& operator=(const non_const_iterator& other) 44 { 45 mp_xpr = other.mp_xpr; 46 m_index = other.m_index; 47 return *this; 48 } 49 50 Derived& operator++() { ++m_index; return derived(); } 51 Derived& operator--() { --m_index; return derived(); } 52 53 Derived operator++(int) { Derived prev(derived()); operator++(); return prev;} 54 Derived operator--(int) { Derived prev(derived()); operator--(); return prev;} 55 56 friend Derived operator+(const indexed_based_stl_iterator_base& a, Index b) { Derived ret(a.derived()); ret += b; return ret; } 57 friend Derived operator-(const indexed_based_stl_iterator_base& a, Index b) { Derived ret(a.derived()); ret -= b; return ret; } 58 friend Derived operator+(Index a, const indexed_based_stl_iterator_base& b) { Derived ret(b.derived()); ret += a; return ret; } 59 friend Derived operator-(Index a, const indexed_based_stl_iterator_base& b) { Derived ret(b.derived()); ret -= a; return ret; } 60 61 Derived& operator+=(Index b) { m_index += b; return derived(); } 62 Derived& operator-=(Index b) { m_index -= b; return derived(); } 63 64 difference_type operator-(const indexed_based_stl_iterator_base& other) const 65 { 66 eigen_assert(mp_xpr == other.mp_xpr); 67 return m_index - other.m_index; 68 } 69 70 difference_type operator-(const other_iterator& other) const 71 { 72 eigen_assert(mp_xpr == other.mp_xpr); 73 return m_index - other.m_index; 74 } 75 76 bool operator==(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } 77 bool operator!=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } 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 83 bool operator==(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } 84 bool operator!=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } 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 90 protected: 91 derived()92 Derived& derived() { return static_cast<Derived&>(*this); } derived()93 const Derived& derived() const { return static_cast<const Derived&>(*this); } 94 95 XprType *mp_xpr; 96 Index m_index; 97 }; 98 99 template<typename Derived> 100 class indexed_based_stl_reverse_iterator_base 101 { 102 protected: 103 typedef indexed_based_stl_iterator_traits<Derived> traits; 104 typedef typename traits::XprType XprType; 105 typedef indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator> non_const_iterator; 106 typedef indexed_based_stl_reverse_iterator_base<typename traits::const_iterator> const_iterator; 107 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator; 108 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class: 109 friend class indexed_based_stl_reverse_iterator_base<typename traits::const_iterator>; 110 friend class indexed_based_stl_reverse_iterator_base<typename traits::non_const_iterator>; 111 public: 112 typedef Index difference_type; 113 typedef std::random_access_iterator_tag iterator_category; 114 indexed_based_stl_reverse_iterator_base()115 indexed_based_stl_reverse_iterator_base() : mp_xpr(0), m_index(0) {} indexed_based_stl_reverse_iterator_base(XprType & xpr,Index index)116 indexed_based_stl_reverse_iterator_base(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {} 117 indexed_based_stl_reverse_iterator_base(const non_const_iterator & other)118 indexed_based_stl_reverse_iterator_base(const non_const_iterator& other) 119 : mp_xpr(other.mp_xpr), m_index(other.m_index) 120 {} 121 122 indexed_based_stl_reverse_iterator_base& operator=(const non_const_iterator& other) 123 { 124 mp_xpr = other.mp_xpr; 125 m_index = other.m_index; 126 return *this; 127 } 128 129 Derived& operator++() { --m_index; return derived(); } 130 Derived& operator--() { ++m_index; return derived(); } 131 132 Derived operator++(int) { Derived prev(derived()); operator++(); return prev;} 133 Derived operator--(int) { Derived prev(derived()); operator--(); return prev;} 134 135 friend Derived operator+(const indexed_based_stl_reverse_iterator_base& a, Index b) { Derived ret(a.derived()); ret += b; return ret; } 136 friend Derived operator-(const indexed_based_stl_reverse_iterator_base& a, Index b) { Derived ret(a.derived()); ret -= b; return ret; } 137 friend Derived operator+(Index a, const indexed_based_stl_reverse_iterator_base& b) { Derived ret(b.derived()); ret += a; return ret; } 138 friend Derived operator-(Index a, const indexed_based_stl_reverse_iterator_base& b) { Derived ret(b.derived()); ret -= a; return ret; } 139 140 Derived& operator+=(Index b) { m_index -= b; return derived(); } 141 Derived& operator-=(Index b) { m_index += b; return derived(); } 142 143 difference_type operator-(const indexed_based_stl_reverse_iterator_base& other) const 144 { 145 eigen_assert(mp_xpr == other.mp_xpr); 146 return other.m_index - m_index; 147 } 148 149 difference_type operator-(const other_iterator& other) const 150 { 151 eigen_assert(mp_xpr == other.mp_xpr); 152 return other.m_index - m_index; 153 } 154 155 bool operator==(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } 156 bool operator!=(const indexed_based_stl_reverse_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } 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 162 bool operator==(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } 163 bool operator!=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } 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 169 protected: 170 derived()171 Derived& derived() { return static_cast<Derived&>(*this); } derived()172 const Derived& derived() const { return static_cast<const Derived&>(*this); } 173 174 XprType *mp_xpr; 175 Index m_index; 176 }; 177 178 template<typename XprType> 179 class pointer_based_stl_iterator 180 { 181 enum { is_lvalue = internal::is_lvalue<XprType>::value }; 182 typedef pointer_based_stl_iterator<typename internal::remove_const<XprType>::type> non_const_iterator; 183 typedef pointer_based_stl_iterator<typename internal::add_const<XprType>::type> const_iterator; 184 typedef typename internal::conditional<internal::is_const<XprType>::value,non_const_iterator,const_iterator>::type other_iterator; 185 // NOTE: in C++03 we cannot declare friend classes through typedefs because we need to write friend class: 186 friend class pointer_based_stl_iterator<typename internal::add_const<XprType>::type>; 187 friend class pointer_based_stl_iterator<typename internal::remove_const<XprType>::type>; 188 public: 189 typedef Index difference_type; 190 typedef typename XprType::Scalar value_type; 191 typedef std::random_access_iterator_tag iterator_category; 192 typedef typename internal::conditional<bool(is_lvalue), value_type*, const value_type*>::type pointer; 193 typedef typename internal::conditional<bool(is_lvalue), value_type&, const value_type&>::type reference; 194 195 pointer_based_stl_iterator()196 pointer_based_stl_iterator() EIGEN_NO_THROW : m_ptr(0) {} pointer_based_stl_iterator(XprType & xpr,Index index)197 pointer_based_stl_iterator(XprType& xpr, Index index) EIGEN_NO_THROW : m_incr(xpr.innerStride()) 198 { 199 m_ptr = xpr.data() + index * m_incr.value(); 200 } 201 pointer_based_stl_iterator(const non_const_iterator & other)202 pointer_based_stl_iterator(const non_const_iterator& other) EIGEN_NO_THROW 203 : m_ptr(other.m_ptr), m_incr(other.m_incr) 204 {} 205 206 pointer_based_stl_iterator& operator=(const non_const_iterator& other) EIGEN_NO_THROW 207 { 208 m_ptr = other.m_ptr; 209 m_incr.setValue(other.m_incr); 210 return *this; 211 } 212 213 reference operator*() const { return *m_ptr; } 214 reference operator[](Index i) const { return *(m_ptr+i*m_incr.value()); } 215 pointer operator->() const { return m_ptr; } 216 217 pointer_based_stl_iterator& operator++() { m_ptr += m_incr.value(); return *this; } 218 pointer_based_stl_iterator& operator--() { m_ptr -= m_incr.value(); return *this; } 219 220 pointer_based_stl_iterator operator++(int) { pointer_based_stl_iterator prev(*this); operator++(); return prev;} 221 pointer_based_stl_iterator operator--(int) { pointer_based_stl_iterator prev(*this); operator--(); return prev;} 222 223 friend pointer_based_stl_iterator operator+(const pointer_based_stl_iterator& a, Index b) { pointer_based_stl_iterator ret(a); ret += b; return ret; } 224 friend pointer_based_stl_iterator operator-(const pointer_based_stl_iterator& a, Index b) { pointer_based_stl_iterator ret(a); ret -= b; return ret; } 225 friend pointer_based_stl_iterator operator+(Index a, const pointer_based_stl_iterator& b) { pointer_based_stl_iterator ret(b); ret += a; return ret; } 226 friend pointer_based_stl_iterator operator-(Index a, const pointer_based_stl_iterator& b) { pointer_based_stl_iterator ret(b); ret -= a; return ret; } 227 228 pointer_based_stl_iterator& operator+=(Index b) { m_ptr += b*m_incr.value(); return *this; } 229 pointer_based_stl_iterator& operator-=(Index b) { m_ptr -= b*m_incr.value(); return *this; } 230 231 difference_type operator-(const pointer_based_stl_iterator& other) const { 232 return (m_ptr - other.m_ptr)/m_incr.value(); 233 } 234 235 difference_type operator-(const other_iterator& other) const { 236 return (m_ptr - other.m_ptr)/m_incr.value(); 237 } 238 239 bool operator==(const pointer_based_stl_iterator& other) const { return m_ptr == other.m_ptr; } 240 bool operator!=(const pointer_based_stl_iterator& other) const { return m_ptr != other.m_ptr; } 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 246 bool operator==(const other_iterator& other) const { return m_ptr == other.m_ptr; } 247 bool operator!=(const other_iterator& other) const { return m_ptr != other.m_ptr; } 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 253 protected: 254 255 pointer m_ptr; 256 internal::variable_if_dynamic<Index, XprType::InnerStrideAtCompileTime> m_incr; 257 }; 258 259 template<typename _XprType> 260 struct indexed_based_stl_iterator_traits<generic_randaccess_stl_iterator<_XprType> > 261 { 262 typedef _XprType XprType; 263 typedef generic_randaccess_stl_iterator<typename internal::remove_const<XprType>::type> non_const_iterator; 264 typedef generic_randaccess_stl_iterator<typename internal::add_const<XprType>::type> const_iterator; 265 }; 266 267 template<typename XprType> 268 class generic_randaccess_stl_iterator : public indexed_based_stl_iterator_base<generic_randaccess_stl_iterator<XprType> > 269 { 270 public: 271 typedef typename XprType::Scalar value_type; 272 273 protected: 274 275 enum { 276 has_direct_access = (internal::traits<XprType>::Flags & DirectAccessBit) ? 1 : 0, 277 is_lvalue = internal::is_lvalue<XprType>::value 278 }; 279 280 typedef indexed_based_stl_iterator_base<generic_randaccess_stl_iterator> Base; 281 using Base::m_index; 282 using Base::mp_xpr; 283 284 // TODO currently const Transpose/Reshape expressions never returns const references, 285 // so lets return by value too. 286 //typedef typename internal::conditional<bool(has_direct_access), const value_type&, const value_type>::type read_only_ref_t; 287 typedef const value_type read_only_ref_t; 288 289 public: 290 291 typedef typename internal::conditional<bool(is_lvalue), value_type *, const value_type *>::type pointer; 292 typedef typename internal::conditional<bool(is_lvalue), value_type&, read_only_ref_t>::type reference; 293 294 generic_randaccess_stl_iterator() : Base() {} 295 generic_randaccess_stl_iterator(XprType& xpr, Index index) : Base(xpr,index) {} 296 generic_randaccess_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {} 297 using Base::operator=; 298 299 reference operator*() const { return (*mp_xpr)(m_index); } 300 reference operator[](Index i) const { return (*mp_xpr)(m_index+i); } 301 pointer operator->() const { return &((*mp_xpr)(m_index)); } 302 }; 303 304 template<typename _XprType, DirectionType Direction> 305 struct indexed_based_stl_iterator_traits<subvector_stl_iterator<_XprType,Direction> > 306 { 307 typedef _XprType XprType; 308 typedef subvector_stl_iterator<typename internal::remove_const<XprType>::type, Direction> non_const_iterator; 309 typedef subvector_stl_iterator<typename internal::add_const<XprType>::type, Direction> const_iterator; 310 }; 311 312 template<typename XprType, DirectionType Direction> 313 class subvector_stl_iterator : public indexed_based_stl_iterator_base<subvector_stl_iterator<XprType,Direction> > 314 { 315 protected: 316 317 enum { is_lvalue = internal::is_lvalue<XprType>::value }; 318 319 typedef indexed_based_stl_iterator_base<subvector_stl_iterator> Base; 320 using Base::m_index; 321 using Base::mp_xpr; 322 323 typedef typename internal::conditional<Direction==Vertical,typename XprType::ColXpr,typename XprType::RowXpr>::type SubVectorType; 324 typedef typename internal::conditional<Direction==Vertical,typename XprType::ConstColXpr,typename XprType::ConstRowXpr>::type ConstSubVectorType; 325 326 327 public: 328 typedef typename internal::conditional<bool(is_lvalue), SubVectorType, ConstSubVectorType>::type reference; 329 typedef typename reference::PlainObject value_type; 330 331 private: 332 class subvector_stl_iterator_ptr 333 { 334 public: 335 subvector_stl_iterator_ptr(const reference &subvector) : m_subvector(subvector) {} 336 reference* operator->() { return &m_subvector; } 337 private: 338 reference m_subvector; 339 }; 340 public: 341 342 typedef subvector_stl_iterator_ptr pointer; 343 344 subvector_stl_iterator() : Base() {} 345 subvector_stl_iterator(XprType& xpr, Index index) : Base(xpr,index) {} 346 347 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); } 348 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index+i); } 349 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); } 350 }; 351 352 template<typename _XprType, DirectionType Direction> 353 struct indexed_based_stl_iterator_traits<subvector_stl_reverse_iterator<_XprType,Direction> > 354 { 355 typedef _XprType XprType; 356 typedef subvector_stl_reverse_iterator<typename internal::remove_const<XprType>::type, Direction> non_const_iterator; 357 typedef subvector_stl_reverse_iterator<typename internal::add_const<XprType>::type, Direction> const_iterator; 358 }; 359 360 template<typename XprType, DirectionType Direction> 361 class subvector_stl_reverse_iterator : public indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator<XprType,Direction> > 362 { 363 protected: 364 365 enum { is_lvalue = internal::is_lvalue<XprType>::value }; 366 367 typedef indexed_based_stl_reverse_iterator_base<subvector_stl_reverse_iterator> Base; 368 using Base::m_index; 369 using Base::mp_xpr; 370 371 typedef typename internal::conditional<Direction==Vertical,typename XprType::ColXpr,typename XprType::RowXpr>::type SubVectorType; 372 typedef typename internal::conditional<Direction==Vertical,typename XprType::ConstColXpr,typename XprType::ConstRowXpr>::type ConstSubVectorType; 373 374 375 public: 376 typedef typename internal::conditional<bool(is_lvalue), SubVectorType, ConstSubVectorType>::type reference; 377 typedef typename reference::PlainObject value_type; 378 379 private: 380 class subvector_stl_reverse_iterator_ptr 381 { 382 public: 383 subvector_stl_reverse_iterator_ptr(const reference &subvector) : m_subvector(subvector) {} 384 reference* operator->() { return &m_subvector; } 385 private: 386 reference m_subvector; 387 }; 388 public: 389 390 typedef subvector_stl_reverse_iterator_ptr pointer; 391 392 subvector_stl_reverse_iterator() : Base() {} 393 subvector_stl_reverse_iterator(XprType& xpr, Index index) : Base(xpr,index) {} 394 395 reference operator*() const { return (*mp_xpr).template subVector<Direction>(m_index); } 396 reference operator[](Index i) const { return (*mp_xpr).template subVector<Direction>(m_index+i); } 397 pointer operator->() const { return (*mp_xpr).template subVector<Direction>(m_index); } 398 }; 399 400 } // namespace internal 401 402 403 /** returns an iterator to the first element of the 1D vector or array 404 * \only_for_vectors 405 * \sa end(), cbegin() 406 */ 407 template<typename Derived> 408 inline typename DenseBase<Derived>::iterator DenseBase<Derived>::begin() 409 { 410 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); 411 return iterator(derived(), 0); 412 } 413 414 /** const version of begin() */ 415 template<typename Derived> 416 inline typename DenseBase<Derived>::const_iterator DenseBase<Derived>::begin() const 417 { 418 return cbegin(); 419 } 420 421 /** returns a read-only const_iterator to the first element of the 1D vector or array 422 * \only_for_vectors 423 * \sa cend(), begin() 424 */ 425 template<typename Derived> 426 inline typename DenseBase<Derived>::const_iterator DenseBase<Derived>::cbegin() const 427 { 428 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); 429 return const_iterator(derived(), 0); 430 } 431 432 /** returns an iterator to the element following the last element of the 1D vector or array 433 * \only_for_vectors 434 * \sa begin(), cend() 435 */ 436 template<typename Derived> 437 inline typename DenseBase<Derived>::iterator DenseBase<Derived>::end() 438 { 439 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); 440 return iterator(derived(), size()); 441 } 442 443 /** const version of end() */ 444 template<typename Derived> 445 inline typename DenseBase<Derived>::const_iterator DenseBase<Derived>::end() const 446 { 447 return cend(); 448 } 449 450 /** returns a read-only const_iterator to the element following the last element of the 1D vector or array 451 * \only_for_vectors 452 * \sa begin(), cend() 453 */ 454 template<typename Derived> 455 inline typename DenseBase<Derived>::const_iterator DenseBase<Derived>::cend() const 456 { 457 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived); 458 return const_iterator(derived(), size()); 459 } 460 461 } // namespace Eigen 462 463 #endif // EIGEN_STLITERATORS_H 464