From 784a3f13cfbb58d51f8c8d49a8c2c424e27ad013 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 9 Nov 2018 21:45:10 +0100 Subject: bug #1619: fix mixing of const and non-const generic iterators --- Eigen/src/Core/StlIterators.h | 85 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 14 deletions(-) (limited to 'Eigen') diff --git a/Eigen/src/Core/StlIterators.h b/Eigen/src/Core/StlIterators.h index e39decc85..131a95085 100644 --- a/Eigen/src/Core/StlIterators.h +++ b/Eigen/src/Core/StlIterators.h @@ -11,9 +11,20 @@ namespace Eigen { namespace internal { -template +template +struct indexed_based_stl_iterator_traits; + +template class indexed_based_stl_iterator_base { +protected: + typedef indexed_based_stl_iterator_traits traits; + typedef typename traits::XprType XprType; + typedef indexed_based_stl_iterator_base non_const_iterator; + typedef indexed_based_stl_iterator_base const_iterator; + typedef typename internal::conditional::value,non_const_iterator,const_iterator>::type other_iterator; + friend const_iterator; + friend non_const_iterator; public: typedef Index difference_type; typedef std::random_access_iterator_tag iterator_category; @@ -21,6 +32,17 @@ public: indexed_based_stl_iterator_base() : mp_xpr(0), m_index(0) {} indexed_based_stl_iterator_base(XprType& xpr, Index index) : mp_xpr(&xpr), m_index(index) {} + indexed_based_stl_iterator_base(const non_const_iterator& other) + : mp_xpr(other.mp_xpr), m_index(other.m_index) + {} + + indexed_based_stl_iterator_base& operator=(const non_const_iterator& other) + { + mp_xpr = other.mp_xpr; + m_index = other.m_index; + return *this; + } + Derived& operator++() { ++m_index; return derived(); } Derived& operator--() { --m_index; return derived(); } @@ -35,14 +57,31 @@ public: Derived& operator+=(Index b) { m_index += b; return derived(); } Derived& operator-=(Index b) { m_index -= b; return derived(); } - difference_type operator-(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr);return m_index - other.m_index; } + difference_type operator-(const indexed_based_stl_iterator_base& other) const + { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index - other.m_index; + } + + difference_type operator-(const other_iterator& other) const + { + eigen_assert(mp_xpr == other.mp_xpr); + return m_index - other.m_index; + } + + bool operator==(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } + bool operator!=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } + bool operator< (const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; } + bool operator<=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; } + bool operator> (const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; } + bool operator>=(const indexed_based_stl_iterator_base& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; } - bool operator==(const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } - bool operator!=(const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } - bool operator< (const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; } - bool operator<=(const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; } - bool operator> (const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; } - bool operator>=(const indexed_based_stl_iterator_base& other) { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; } + bool operator==(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index == other.m_index; } + bool operator!=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index != other.m_index; } + bool operator< (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index < other.m_index; } + bool operator<=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index <= other.m_index; } + bool operator> (const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index > other.m_index; } + bool operator>=(const other_iterator& other) const { eigen_assert(mp_xpr == other.mp_xpr); return m_index >= other.m_index; } protected: @@ -57,8 +96,8 @@ template class pointer_based_stl_iterator { enum { is_lvalue = internal::is_lvalue::value }; - typedef pointer_based_stl_iterator::type > non_const_iterator; - typedef pointer_based_stl_iterator::type > const_iterator; + typedef pointer_based_stl_iterator::type> non_const_iterator; + typedef pointer_based_stl_iterator::type> const_iterator; typedef typename internal::conditional::value,non_const_iterator,const_iterator>::type other_iterator; friend const_iterator; friend non_const_iterator; @@ -133,8 +172,16 @@ protected: internal::variable_if_dynamic m_incr; }; +template +struct indexed_based_stl_iterator_traits > +{ + typedef _XprType XprType; + typedef generic_randaccess_stl_iterator::type> non_const_iterator; + typedef generic_randaccess_stl_iterator::type> const_iterator; +}; + template -class generic_randaccess_stl_iterator : public indexed_based_stl_iterator_base > +class generic_randaccess_stl_iterator : public indexed_based_stl_iterator_base > { public: typedef typename XprType::Scalar value_type; @@ -146,7 +193,7 @@ protected: is_lvalue = internal::is_lvalue::value }; - typedef indexed_based_stl_iterator_base Base; + typedef indexed_based_stl_iterator_base Base; using Base::m_index; using Base::mp_xpr; @@ -162,20 +209,30 @@ public: generic_randaccess_stl_iterator() : Base() {} generic_randaccess_stl_iterator(XprType& xpr, Index index) : Base(xpr,index) {} + generic_randaccess_stl_iterator(const typename Base::non_const_iterator& other) : Base(other) {} + using Base::operator=; reference operator*() const { return (*mp_xpr)(m_index); } reference operator[](Index i) const { return (*mp_xpr)(m_index+i); } pointer operator->() const { return &((*mp_xpr)(m_index)); } }; +template +struct indexed_based_stl_iterator_traits > +{ + typedef _XprType XprType; + typedef subvector_stl_iterator::type, Direction> non_const_iterator; + typedef subvector_stl_iterator::type, Direction> const_iterator; +}; + template -class subvector_stl_iterator : public indexed_based_stl_iterator_base > +class subvector_stl_iterator : public indexed_based_stl_iterator_base > { protected: enum { is_lvalue = internal::is_lvalue::value }; - typedef indexed_based_stl_iterator_base Base; + typedef indexed_based_stl_iterator_base Base; using Base::m_index; using Base::mp_xpr; -- cgit v1.2.3