
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@abirbasak.com homepage: www.abirbasak.com