Boost logo

Boost Users :

From: abir basak (abirbasak_at_[hidden])
Date: 2007-02-22 04:26:59


abir basak wrote:
> Hi,
> It is an extension to one my previous post, where I needed help while
> giving access to a sub_range for of an container.
> In that problem , Mr Thorsten Ottosen, provided answer to all of my
> queries (Many thanks to him ).
>
> This time I am interested to provide indexed access to a vector with a
> sub_range ,using permutation_iterator.
> Here some codes are creating problem, while I am using sub_range with
> permutation iterator.
>
> To specify, I am providing a small test code.
> typedef std::pair<std::size_t,std::size_t> pair_t;
> template<typename T>
> class vector_e : private std::vector<T>{
> public:
> typedef vector_e<T> self_type;
> typedef typename std::vector<T>::iterator iterator;
> typedef typename std::vector<T>::const_iterator const_iterator;
> typedef boost::sub_range<self_type> range;
> typedef boost::sub_range<const self_type> const_range;
> typedef typename std::vector<T>::size_type size_type;
> typedef std::vector<int> index_type;
> typedef typename boost::permutation_iterator<typename
> iterator,index_type::const_iterator> index_iterator;
> typedef typename boost::permutation_iterator<typename
> const_iterator,index_type::const_iterator> const_index_iterator;
> vector_e() : std::vector<T>(){}
> using std::vector<T>::begin;
> using std::vector<T>::end;
> using std::vector<T>::operator [];
> using std::vector<T>::insert;
> index_iterator begin_i(const index_type& i){
> return boost::make_permutation_iterator(begin(),i.begin());
> }
> const_index_iterator begin_i(const index_type& i)const{
> return boost::make_permutation_iterator(begin(),i.begin());
> }
>
> index_iterator end_i(const index_type& i){
> return boost::make_permutation_iterator(begin(),i.end());
> }
> const_index_iterator end_i(const index_type& i)const{
> return boost::make_permutation_iterator(begin(),i.end());
> }
> range get_range(const pair_t& range){
> return
> boost::make_iterator_range(begin()+range.first,begin()+range.second);
> }
> const_range get_range(const pair_t& range)const{
> return
> boost::make_iterator_range(begin()+range.first,begin()+range.second);
> }
> range get_range(const index_type& i){
> return
> boost::make_iterator_range(boost::make_permutation_iterator(begin(),i.begin()),
> boost::make_permutation_iterator(begin(),i.end()));
> }
> };
> int main(int argc,char** argv) {
> using namespace boost;
> using namespace boost::assign;
> using namespace boost::lambda;
> using boost::lambda::_1;
> typedef vector_e<int> elem_t;
> typedef std::vector<int> index_t;
> elem_t v;
> int a[] = {00,10,20,30,40,50,60,70,80,90,100};
> v.insert(v.end(),a,a+11);
> const elem_t& cv = const_cast<elem_t&>(v);
> //v+= 00,10,20,30,40,50,60,70,80,90,100;
> std::cout<<"original array : ";
> std::for_each(v.begin(),v.end(),std::cout<<_1<<" ");
> ///For continuous ranges.
> elem_t::range r = v.get_range(std::make_pair(1,5));
> std::cout<<std::endl<<" range (1,5) : ";
> ///working fine
> std::for_each(r.begin(),r.end(),std::cout<<_1<<" ");
> ///working fine
> elem_t::const_range cr = v.get_range(std::make_pair(1,5));
> std::cout<<std::endl<<" c_range (1,5) : ";
> std::for_each(cr.begin(),cr.end(),std::cout<<_1<<" ");
> ///working fine
> elem_t::const_range cr1 = cv.get_range(std::make_pair(1,5));
> std::cout<<std::endl<<" c_range1 (1,5) : ";
> std::for_each(cr1.begin(),cr1.end(),std::cout<<_1<<" ");
>
> index_t i;
> i+=0,2,6,4,9;
> std::cout<<std::endl<<" index : ";
> std::for_each(i.begin(),i.end(),std::cout<<_1<<" ");
> std::cout<<std::endl<<"index range ";
> //working fine
> std::for_each(v.begin_i(i),v.end_i(i),std::cout<<_1 << " ");
> std::cout<<std::endl<<"c index range ";
> ///working fine
> std::for_each(cv.begin_i(i),cv.end_i(i),std::cout<<_1 << " ");
> ///not working (and its const counter part )
> elem_t::range ir = v.get_range(i);
> }
> The error it is giving in visual studio 7.1 for sub_range of
> permutation_iterator is,
> E:\boost_1_33_1\boost\range\iterator_range.hpp(60): error C2440: 'type
> cast' : cannot convert from 'boost::range_iterator<C>::type' to
> 'boost::range_iterator<C>::type'
> with
> [
> C=const boost::iterator_range<vector_e<int>::index_iterator>
> ]
> and
> [
> C=vector_e<int>::self_type
> ]
>
> The questions are
> 1) Can anyone point out the problem ? (Is sub_range is typed by iterator
> by any chance, or typed by container only ? )
> 2) This is aux question. How to make assign library work for my
> inherited container (vector_e here ), like the commented line ?
>
>
> any help is appreciated, and thanks to the community .
>
> abir
>
>
>
Once again.
I was looking at the boost::sub_range & iterator_range code (also crange
  & irange code). It looks, though sub_range and crange are typed over
container, they use the iterator (or const_iterator, depending on the
container ) as the iterator to iterate over the range. And it seems that
is the problem I am facing.
Where my range needs a user specified iterator (or iterator adapter ) to
iterate over the container.
Thus I tried to have my iterator pass as template parameter.
The sub_range class now looks like,
template<typename C, typename I = typename container_traits<C>::iterator,
typename CI = typename container_traits<C>::const_iterator>
class sub_range_t{
public:
        typedef typename I iterator;
        typedef typename CI const_iterator;
        typedef typename container_traits<C>::reference reference;
        typedef typename container_traits<C>::pointer pointer;
        typedef typename container_traits<C>::size_type size_type;

private:
        iterator begin_;
        iterator end_;
public:
        //template<typename C>sub_range_t(C& c) : begin_(c.begin() ),
end_(c.end()) {}
        //template<typename C>sub_range_t(const C& c)
:begin_(c.begin()),end_(c.end()){}
        sub_range_t(iterator& begin,iterator& end) : begin_(begin),end_(end){}
        sub_range_t(::std::pair<iterator,iterator>& p) : begin_(p.first) ,
end_(p.second){}
        template<typename r> sub_range_t(const sub_range_t<r>& other) :
begin_(other.begin()),
                end_(other.end()){}
        iterator begin() const{ return begin_;}
        iterator end() const { return end_;}
        const_iterator const_begin() const { return begin_;}
        const_iterator const_end() const { return end_;}

        reference operator[]( size_type n) { return begin_[n]; }

};
Here, Now I can work with permutation_iterator (or any other iterator by
specifying it).
This class is not sufficient. It lacks 2 things (other than having
insufficient member functions )
1) The 2 commented ctor doesn't work . Need to check how to make that work.
2) elem_t::const_index_range cir1 = v.get_range(i); this still doesn't
work. i.e a non const range => const range conversion doesn't work.

The additional typedef's are, for vector_e class
typedef typename boost::permutation_iterator<typename iterator,typename
index_type::const_iterator> index_iterator;
        typedef typename boost::permutation_iterator<typename
const_iterator,typename index_type::const_iterator> const_index_iterator;
        typedef sub_range_t<self_type,index_iterator,const_index_iterator>
index_range;
        typedef
sub_range_t<self_type,const_index_iterator,const_index_iterator>
const_index_range;

Also, instead of this kind of class, I prefer to have a range adapter to
create this ranges just like iterator_adapter.
I am not sure if this is already possible in boost, or some library yet
to be submitted. Or directly iterator_range gives this facility ?
(including the facility to preserve const-ness . I wont surprised if it
can do so :) )

Can anybody give some hint ?

-- 
Abir Basak, Member IEEE
Software Engineer, Read Ink Technologies
B. Tech, IIT Kharagpur
email: abir_at_[hidden]
homepage: www.abirbasak.com

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