|
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