Boost logo

Boost Users :

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);
    }

};


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net