$include_dir="/home/hyper-archives/boost-users/include"; include("$include_dir/msg-header.inc") ?>
From: e r (erwann.rogard_at_[hidden])
Date: 2008-08-19 23:27:32
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);
    }
};