dereference problems with iterator_facade

hello, i have a build error when i try to use an iterator derived from iterator_facade<Iter> with Iter an iterator over a const Range. It's the const that causes the error. See the *.hpp below and an example. any other suggestion to improve the *hpp also appreciated. thanks! /////////////////////////////////////////////////////////////////////////////// // boost::skip_one_step_iterator.hpp // // Copyright 2008 Erwann Rogard. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_ITERATOR_SKIP_ONE_STEP_ITERATOR_HPP_ER200808 #define BOOST_ITERATOR_SKIP_ONE_STEP_ITERATOR_HPP_ER200808 #include <iterator> #include <stdexcept> #include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_traits.hpp> #include <boost/range.hpp> #include <boost/assert.hpp> #include <boost/type_traits.hpp> namespace boost{ namespace{ template<typename BaseIter,typename Derived> struct super{ typedef iterator_facade< Derived, typename iterator_value<BaseIter>::type, typename iterator_category<BaseIter>::type> type; }; } template<typename BaseIter> class skip_one_step_iterator : public super<BaseIter,skip_one_step_iterator<BaseIter> >::type { typedef iterator_range<BaseIter> iterator_range_type; typedef typename super<BaseIter,skip_one_step_iterator>::type super_type; public: typedef typename super_type::difference_type difference_type; typedef typename super_type::reference reference; skip_one_step_iterator(){} explicit skip_one_step_iterator( BaseIter i, BaseIter skip ) :base_iter(i),skip_(skip){ if(base_is_skip()){ throw std::runtime_error( "skip_one_step_iterator: base_is_skip at construction" ); } } private: friend class boost::iterator_core_access; void increment() { advance((difference_type)(1)); } difference_type distance_to(skip_one_step_iterator const& other) const{ difference_type d = std::distance(this->base_iter,other.base_iter); difference_type dist_this = std::distance(this->base_iter,skip_); difference_type dist_other = std::distance(other.base_iter,skip_); bool same_sign = ((dist_this<0) && (dist_other<0)) || ((dist_this>0) && (dist_other>0)); if(!same_sign){ if(d<(difference_type)(0)){ d+=(difference_type)(1); }else{ d-=(difference_type)(1); } } return d; } bool equal(skip_one_step_iterator const& other) const { return this->base_iter == other.base_iter; } reference dereference() const { return *base_iter; } void advance(difference_type n) { std::advance(this->base_iter,1); if(base_is_skip()){ std::advance(this->base_iter,1); } } bool base_is_skip()const{ return ((this->base_iter)==(this->skip_)); } BaseIter base_iter; BaseIter skip_; }; template<typename Iter> skip_one_step_iterator<Iter> make_skip_one_step_begin_iterator(Iter b,Iter skip){ Iter new_b = b; if(new_b == skip){ std::advance(new_b,1); } return skip_one_step_iterator<Iter>(new_b,skip); }; template<typename Iter> skip_one_step_iterator<Iter> make_skip_one_step_end_iterator(Iter e,Iter skip){ // constructor below will throw if skip == e return skip_one_step_iterator<Iter>(e,skip); }; } #endif #include <iostream> #include <vector> #include <iterator> #include <boost/range.hpp> #include <boost/assign/std/vector.hpp> #include <boost/iterator/skip_one_step_iterator.hpp> #include <libs/iterator/example/skip_one_step_iterator.h> template<typename R> void func(const R& range,std::size_t i){ //void func(R& range,std::size_t i)//works fine //typedef R range_type;//works fine typedef const R range_type; typedef typename boost::range_iterator<range_type>::type iter_type; typedef boost::skip_one_step_iterator<iter_type> skipr_iter_type; iter_type b = boost::begin(range); iter_type e = boost::end(range); iter_type skip = b; std::advance(skip,i); skipr_iter_type sb = boost::make_skip_one_step_begin_iterator(b,skip); skipr_iter_type se = boost::make_skip_one_step_end_iterator(e,skip); copy( sb, se, std::ostream_iterator<double>(std::cout<<" "," ") ); std::cout << std::endl; }; void example_skip_one_step_iterator(){ using namespace boost; typedef std::vector<double> vector_type; typedef vector_type::size_type size_type; typedef range_iterator<vector_type>::type iter_type; typedef skip_one_step_iterator<iter_type> skipr_iter_type; vector_type vec; { using namespace boost::assign; vec += 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0; } //invalid initialization of reference of type ‘double&’ from expression of type ‘const double’| //this error disappears if range_type replaced by R in definition of func for(size_type i = 1; i < size(vec); i++){ std::cout << "i=" << i << std::endl; func(vec,i); } };

on Tue Aug 19 2008, e r <erwann.rogard-AT-gmail.com> wrote:
hello,
i have a build error when i try to use an iterator derived from iterator_facade<Iter> with Iter an iterator over a const Range. It's the const that causes the error. See the *.hpp below and an example.
The problem is that the reference type of Iter is value_type& when it should be value_type const&. The value_type of a constant iterator is still non-const, and you're getting the Value parameter by asking the value_type of BaseIter.
any other suggestion to improve the *hpp also appreciated.
Use iterator_adaptor; all your problems will go away and your code will get smaller. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Tue Aug 19 2008, e r <erwann.rogard-AT-gmail.com> wrote:
hello,
i have a build error when i try to use an iterator derived from iterator_facade<Iter> with Iter an iterator over a const Range. It's the const that causes the error. See the *.hpp below and an example.
The problem is that the reference type of Iter is value_type& when it should be value_type const&. The value_type of a constant iterator is still non-const, and you're getting the Value parameter by asking the value_type of BaseIter.
any other suggestion to improve the *hpp also appreciated.
Use iterator_adaptor; all your problems will go away and your code will get smaller.
Indeed, it worked. Thanks^2!
participants (2)
-
David Abrahams
-
e r