Another sub_range problem

Hi, I am facing some more range problem from boost::range; According to the CVS RC_1_34 works. Revision 1.21 version specified by Thorsten Ottosen , most of the classes work. What is my interest is to have a get_range function inside some of the container class like std::vector and boost::circular_buffer (from boost CVS) Here I have test class to show the problem I am facing. First, when I inherit from a vector , and specify a range function just like iterator functions ( begin() and end() ) template<typename T> class range_vector : public std::vector<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; range get_range(size_type from,size_type to){ std::cout<<"range"<<std::endl; return range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ std::cout<<"const range"<<std::endl; return const_range(begin()+from,begin()+to); } }; int main(){ range_vector<int> v; int x[] = {0,1,2,3,4,5,6,7,8}; v.insert(v.end(),x,x+9); std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; range_vector<int>::range r = v.get_range(1,5); r[0] = 100; copy(r.begin(),r.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; range_vector<int>::const_range cr = v.get_range(1,5); copy(cr.begin(),cr.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; const range_vector<int>& cv = v; range_vector<int>::const_range cr1 = cv.get_range(1,5); copy(cr.begin(),cr.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } This code compiles perfectly and gives result as expected. It also works with deque . However when I compile the same code for boost::circular_buffer,i.e template<typename T> class range_vector : public boost::circular_buffer<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; range get_range(size_type from,size_type to){ std::cout<<"range"<<std::endl; return range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ std::cout<<"const range"<<std::endl; return const_range(begin()+from,begin()+to); } }; It has a same interface that of a vector, it fails to compile when I call the non-const get_range function. i.e //Initialized the circular_buffer with a few elements. range_vector<int> v; int x[] = {0,1,2,3,4,5,6,7,8}; v.insert(v.end(),x,x+9); std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; ///got a const reference and invoking const version of get_range. works fine. const range_vector<int>& cv = v; range_vector<int>::const_range cr1 = cv.get_range(1,5); copy(cr1.begin(),cr1.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; ///now trying to get a non-const version range_vector<int>::range r = v.get_range(1,5); Here it gives error in Visual Studio 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::sub_range<range_vector<int>> ] and [ C=range_vector<int> ] ///now trying to get a non-version and assign it to const version range_vector<int>::const_range r = v.get_range(1,5); It gives the same error. Here C (container) is passed as correct one. begin() and end() are too executes correct version (non-const one). Not getting why it won't work. Any kind of help is highly appreciated. Thanks to boost community in advance. abir basak -- Abir Basak, Member IEEE Software Engineer, Read Ink Technologies B. Tech, IIT Kharagpur email: abir@abirbasak.com homepage: www.abirbasak.com

abir basak wrote:
Hi, I am facing some more range problem from boost::range; According to the CVS RC_1_34 works. Revision 1.21 version specified by Thorsten Ottosen , most of the classes work. What is my interest is to have a get_range function inside some of the container class like std::vector and boost::circular_buffer (from boost CVS) Here I have test class to show the problem I am facing. First, when I inherit from a vector , and specify a range function just like iterator functions ( begin() and end() )
template<typename T> class range_vector : public std::vector<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; range get_range(size_type from,size_type to){ std::cout<<"range"<<std::endl; return range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ std::cout<<"const range"<<std::endl; return const_range(begin()+from,begin()+to); } }; int main(){ range_vector<int> v; int x[] = {0,1,2,3,4,5,6,7,8}; v.insert(v.end(),x,x+9); std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; range_vector<int>::range r = v.get_range(1,5); r[0] = 100; copy(r.begin(),r.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; range_vector<int>::const_range cr = v.get_range(1,5); copy(cr.begin(),cr.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; const range_vector<int>& cv = v; range_vector<int>::const_range cr1 = cv.get_range(1,5); copy(cr.begin(),cr.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; } This code compiles perfectly and gives result as expected. It also works with deque .
However when I compile the same code for boost::circular_buffer,i.e template<typename T> class range_vector : public boost::circular_buffer<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; range get_range(size_type from,size_type to){ std::cout<<"range"<<std::endl; return range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ std::cout<<"const range"<<std::endl; return const_range(begin()+from,begin()+to); } }; It has a same interface that of a vector, it fails to compile when I call the non-const get_range function. i.e //Initialized the circular_buffer with a few elements. range_vector<int> v; int x[] = {0,1,2,3,4,5,6,7,8}; v.insert(v.end(),x,x+9); std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl;
///got a const reference and invoking const version of get_range. works fine. const range_vector<int>& cv = v; range_vector<int>::const_range cr1 = cv.get_range(1,5); copy(cr1.begin(),cr1.end(),std::ostream_iterator<int>(std::cout," ")); std::cout<<std::endl; ///now trying to get a non-const version range_vector<int>::range r = v.get_range(1,5); Here it gives error in Visual Studio 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::sub_range<range_vector<int>> ] and [ C=range_vector<int> ]
///now trying to get a non-version and assign it to const version range_vector<int>::const_range r = v.get_range(1,5); It gives the same error. Here C (container) is passed as correct one. begin() and end() are too executes correct version (non-const one). Not getting why it won't work.
Any kind of help is highly appreciated. Thanks to boost community in advance.
abir basak To make the problem little clearer, typedef boost::circular_buffer<int> cbi; typedef std::vector<int> vi; This code works, boost::sub_range<vi> get_range(vi& v,int from,int to){ return boost::sub_range<vi>(v.begin()+from,v.begin()+to); } But this don't. boost::sub_range<cbi> get_range(cbi& v,int from,int to){ return boost::sub_range<cbi>(v.begin()+from,v.begin()+to); }
-- Abir Basak, Member IEEE Software Engineer, Read Ink Technologies B. Tech, IIT Kharagpur email: abir@abirbasak.com homepage: www.abirbasak.com

abir basak wrote:
abir basak wrote:
To make the problem little clearer, typedef boost::circular_buffer<int> cbi; typedef std::vector<int> vi; This code works, boost::sub_range<vi> get_range(vi& v,int from,int to){ return boost::sub_range<vi>(v.begin()+from,v.begin()+to); } But this don't. boost::sub_range<cbi> get_range(cbi& v,int from,int to){ return boost::sub_range<cbi>(v.begin()+from,v.begin()+to); }
Try to make the example even smaller so you can post it to the list as a complete example that does not require any additional dependencies. I will try it out then. -Thorsten

Thorsten Ottosen wrote:
abir basak wrote:
abir basak wrote:
To make the problem little clearer, typedef boost::circular_buffer<int> cbi; typedef std::vector<int> vi; This code works, boost::sub_range<vi> get_range(vi& v,int from,int to){ return boost::sub_range<vi>(v.begin()+from,v.begin()+to); } But this don't. boost::sub_range<cbi> get_range(cbi& v,int from,int to){ return boost::sub_range<cbi>(v.begin()+from,v.begin()+to); }
Try to make the example even smaller so you can post it to the list as a complete example that does not require any additional dependencies.
I will try it out then.
I found a solution in the mean-time. I had just overlooked the make_iterator_range function, which serves the purpose. But still I feels some problem is there with the copy ctor of sub_range (or may be copy ctor of iterator_range ) with Visual Studio 2003 (7.1) and 2005 (8.0 ) compiler version. All of the example runs perfectly with MinGW (GCC mingw build 3.4.5 version). I am trying to give a compilable example. 1) #include <iterator> #include <memory> #include <vector> #include <iostream> #include <boost/circular_buffer.hpp> #include <boost/range.hpp> template<typename T> class range_vector : public boost::circular_buffer<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; typedef typename boost::circular_buffer<T>::size_type size_type; using boost::circular_buffer<T>::begin; range_vector(size_type capacity) : boost::circular_buffer<T>(capacity){} range get_range(size_type from,size_type to){ return range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ return const_range(begin()+from,begin()+to); } }; typedef range_vector<int> rvi; int main() { rvi v(9); int x[] = {0,1,2,3,4,5,6,7,8}; v.insert(v.end(),x,x+9); rvi::range r1(v.get_range(1,5)); ///get_range causes error in VS 7.1 & 8.0 problem is likely due to copy-ctor of sub_range. Works fine on MinGW. } VS error 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::sub_range<range_vector<int>> ] and [ C=range_vector<int> ] Inheriting range_vector from std::vector works fine for both compilers. 2) However changing the range_vector<T> class as below works for both compiler. Note, here it uses boost::make_iterator_range instead. template<typename T> class range_vector : public boost::circular_buffer<T>{ public: typedef boost::sub_range<range_vector> range; typedef boost::sub_range<const range_vector> const_range; typedef typename boost::circular_buffer<T>::size_type size_type; using boost::circular_buffer<T>::begin; range_vector(size_type capacity) : boost::circular_buffer<T>(capacity){} range get_range(size_type from,size_type to){ return boost::make_iterator_range(begin()+from,begin()+to); } const_range get_range(size_type from,size_type to)const{ return boost::make_iterator_range(begin()+from,begin()+to); } }; Not sure if it is an error. You can check if that one is expected behavior. But it works with make_iterator_range, which I had overlooked. Thanks for listening. abir
-Thorsten
-- Abir Basak, Member IEEE Software Engineer, Read Ink Technologies B. Tech, IIT Kharagpur email: abir@abirbasak.com homepage: www.abirbasak.com

abir basak wrote:
abir basak wrote: To make the problem little clearer, typedef boost::circular_buffer<int> cbi; typedef std::vector<int> vi; This code works, boost::sub_range<vi> get_range(vi& v,int from,int to){ return boost::sub_range<vi>(v.begin()+from,v.begin()+to); } But this don't. boost::sub_range<cbi> get_range(cbi& v,int from,int to){ return boost::sub_range<cbi>(v.begin()+from,v.begin()+to); }
FWIW, under VC8, boost::sub_range is not always CopyConstructible. You can prefer boost::iterator_range instead. This behavior comes from the VC8 bug. (See: http://tinyurl.com/yb8ban) Put simply, her implicitly-defined copy-constructor/copy-assignment-operator is not conforming. IIRC, VC7.1 also has this bug under weird situation, but I'm not sure. The copy-assignment-operator of boost::sub_range(CVS Head) seems to be patched for that bug, but the copy-constructor seems not yet? -- Shunsuke Sogame
participants (3)
-
abir basak
-
Shunsuke Sogame
-
Thorsten Ottosen