[ptr_container] iterators bug

I get compiler error if I try to compare ptr_vector::iterator with ptr_vector::const_iterator. (I use the latest library downloaded from Boost CVS repository) For example, the following code doesn't compile under VC 7.1: typedef boost::ptr_vector<char> TContainer; TContainer some_vector; for (TContainer::const_iterator it = some_vector.begin(); it != some_vector.end(); ++it) ; But it definitely should...

Hi Alexey, "Alexey Bakhvalov" <bakhvalov@gmail.com> wrote in message news:d8kjpe$amo$1@sea.gmane.org... |I get compiler error if I try to compare ptr_vector::iterator with | ptr_vector::const_iterator. (I use the latest library downloaded from Boost | CVS repository) | For example, the following code doesn't compile under VC 7.1: | | typedef boost::ptr_vector<char> TContainer; | TContainer some_vector; | for (TContainer::const_iterator it = some_vector.begin(); it != | some_vector.end(); ++it) ; | | But it definitely should... yes, it should. (note, however, you can hoist the end() computation out of the loop) I'm a bit reluctant to commit anything at this point unless the release manager accepts it. Doug, is it ok to commit the patch + opdated test? (All test runs (and works) with vc7.1, gcc3.3.3, como4.3.3) -Thorsten

Btw, I get similar error if I try to subtract iterator from const_iterator (or vice versa). Example: typedef boost::ptr_vector<char> TContainer; TContainer some_vector; TContainer::const_iterator it1 = some_vector.begin(); TContainer::iterator it2 = some_vector.begin(); size_t diff = it1 - it2; It seems that there is a problem with all binary operators that take iterators as operands.

"Alexey Bakhvalov" <bakhvalov@gmail.com> wrote in message news:d8l314$p0h$1@sea.gmane.org... | Btw, I get similar error if I try to subtract iterator from const_iterator | (or vice versa). | Example: | | typedef boost::ptr_vector<char> TContainer; | TContainer some_vector; | TContainer::const_iterator it1 = some_vector.begin(); | TContainer::iterator it2 = some_vector.begin(); | size_t diff = it1 - it2; | | It seems that there is a problem with all binary operators that take | iterators as operands. ah yes. I haven't got time to look in the standard, but must iterator and const_iterator be completely interchangable? -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:d8nb2d$92j$1@sea.gmane.org...
"Alexey Bakhvalov" <bakhvalov@gmail.com> wrote in message news:d8l314$p0h$1@sea.gmane.org... | Btw, I get similar error if I try to subtract iterator from const_iterator | (or vice versa). | Example: | | typedef boost::ptr_vector<char> TContainer; | TContainer some_vector; | TContainer::const_iterator it1 = some_vector.begin(); | TContainer::iterator it2 = some_vector.begin(); | size_t diff = it1 - it2; | | It seems that there is a problem with all binary operators that take | iterators as operands.
ah yes. I haven't got time to look in the standard, but must iterator and const_iterator be completely interchangable?
I can't find anything in the standard that would explicitly state this but I thought that random iterators should mimic regular pointers in as many ways as possible (and language allows such operations on pointers). It would be good if someone else could comment on this issue.

"Alexey Bakhvalov" <bakhvalov@gmail.com> writes:
"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:d8nb2d$92j$1@sea.gmane.org...
"Alexey Bakhvalov" <bakhvalov@gmail.com> wrote in message news:d8l314$p0h$1@sea.gmane.org... | Btw, I get similar error if I try to subtract iterator from const_iterator | (or vice versa). | Example: | | typedef boost::ptr_vector<char> TContainer; | TContainer some_vector; | TContainer::const_iterator it1 = some_vector.begin(); | TContainer::iterator it2 = some_vector.begin(); | size_t diff = it1 - it2; | | It seems that there is a problem with all binary operators that take | iterators as operands.
ah yes. I haven't got time to look in the standard, but must iterator and const_iterator be completely interchangable?
I can't find anything in the standard that would explicitly state this but I thought that random iterators should mimic regular pointers in as many ways as possible (and language allows such operations on pointers). It would be good if someone else could comment on this issue.
If someone would clearly and succinctly spell out the question, I'd be happy to. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com... | If someone would clearly and succinctly spell out the question, I'd be | happy to. should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container? -Thorsten

On Wed, Jun 15, 2005 at 10:24:10AM +0200, Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com...
| If someone would clearly and succinctly spell out the question, I'd be | happy to.
should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container?
It's not required for any iterator in general (you can't convert all output iterators to input iterators, for instance ostream_iterator cannot be converted to a read-only iterator type). But the container requirements require that X::iterator be convertible to X::const_iterator, and then all those operations work by using that conversion. That is analogous to implicit T* -> const T* conversion. So yes, for random access iterators it should work (and all other iterators for containers). jon -- "With consistency a great soul has simply nothing to do." - Ralph Waldo Emerson

Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Wed, Jun 15, 2005 at 10:24:10AM +0200, Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com...
| If someone would clearly and succinctly spell out the question, I'd be | happy to.
should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container?
It's not required for any iterator in general (you can't convert all output iterators to input iterators, for instance ostream_iterator cannot be converted to a read-only iterator type).
But the container requirements require that X::iterator be convertible to X::const_iterator, and then all those operations work by using that conversion.
That's incorrect. For example, if the operations are templated no implicit conversion will take place. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u3brjtxrc.fsf@boost-consulting.com... | Jonathan Wakely <cow@compsoc.man.ac.uk> writes: | > But the container requirements require that X::iterator be convertible | > to X::const_iterator, and then all those operations work by using that | > conversion. | | That's incorrect. For example, if the operations are templated no | implicit conversion will take place. would it be correct to implement the binary operators in my "wrapping" iterators as function templates. template< class VoidIter, class VoidIter2 > inline bool operator==( const iter<VoidIter>& l, const iter<VoidIter2>& r ) { return l.base() == r.base(); } ? (At least that is how I do it now) -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:u3brjtxrc.fsf@boost-consulting.com... | Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
| > But the container requirements require that X::iterator be convertible | > to X::const_iterator, and then all those operations work by using that | > conversion. | | That's incorrect. For example, if the operations are templated no | implicit conversion will take place.
would it be correct to implement the binary operators in my "wrapping" iterators as function templates.
It would be correct to use iterator_adaptor. Why aren't you doing that?
template< class VoidIter, class VoidIter2 > inline bool operator==( const iter<VoidIter>& l, const iter<VoidIter2>& r ) { return l.base() == r.base(); }
?
Sure, but you might want to use disable_if to prevent overeager matching. Of course the iterators library will take care of this for you. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uhdfzphdr.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > would it be correct to implement the binary operators in my "wrapping" | > iterators | > as function templates. | | It would be correct to use iterator_adaptor. Why aren't you doing | that? because I need to apply a cast form void* to T* in operator*() and operator->(). -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uhdfzphdr.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
| > would it be correct to implement the binary operators in my "wrapping" | > iterators | > as function templates. | | It would be correct to use iterator_adaptor. Why aren't you doing | that?
because I need to apply a cast form void* to T* in operator*() and operator->().
Seems like a perfect job for transform_iterator to me. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:u1x73meya.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | | > "David Abrahams" <dave@boost-consulting.com> wrote in message | > news:uhdfzphdr.fsf@boost-consulting.com... | > | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > | > | > would it be correct to implement the binary operators in my "wrapping" | > | > iterators | > | > as function templates. | > | | > | It would be correct to use iterator_adaptor. Why aren't you doing | > | that? | > | > because I need to apply a cast form void* to T* in operator*() and | > operator->(). | | Seems like a perfect job for transform_iterator to me. it does! I used the operators helper classes, but moved away from them due to portability reasons. Anyway, I will look into this in the future. -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:d8qf4a$ac7$1@sea.gmane.org... | "David Abrahams" <dave@boost-consulting.com> wrote in message || Seems like a perfect job for transform_iterator to me. | | it does! I used the operators helper classes, but moved away from them due to | portability | reasons. Anyway, I will look into this in the future. As for the map_iterator, then the interface has changed, so the adapters don't work. (the iterator supports .key() and * returns a reference to the value type, and not a pair) As for void_ptr_iterator, I guess it could be replaced with transform_iterator. I'm not sure if portability will suffer because of it, but I supsect it. I used operator.hpp to begin with, but moved awau due to portability reasons (vc6 stuff, I think). --Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"Thorsten Ottosen" <nesotto@cs.auc.dk> wrote in message news:d8qf4a$ac7$1@sea.gmane.org... | "David Abrahams" <dave@boost-consulting.com> wrote in message
|| Seems like a perfect job for transform_iterator to me. | | it does! I used the operators helper classes, but moved away from them due to | portability | reasons. Anyway, I will look into this in the future.
As for the map_iterator, then the interface has changed, so the adapters don't work. (the iterator supports .key() and * returns a reference to the value type, and not a pair)
Then just build your own using iterator_adaptor.
As for void_ptr_iterator, I guess it could be replaced with transform_iterator. I'm not sure if portability will suffer because of it, but I supsect it.
Why?
I used operator.hpp to begin with, but moved awau due to portability reasons (vc6 stuff, I think).
The two have little to do with one another. The iterators library is highly portable. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Wed, Jun 15, 2005 at 12:01:27PM -0400, David Abrahams wrote:
Jonathan Wakely <cow@compsoc.man.ac.uk> writes:
On Wed, Jun 15, 2005 at 10:24:10AM +0200, Thorsten Ottosen wrote:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com...
| If someone would clearly and succinctly spell out the question, I'd be | happy to.
should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container?
It's not required for any iterator in general (you can't convert all output iterators to input iterators, for instance ostream_iterator cannot be converted to a read-only iterator type).
But the container requirements require that X::iterator be convertible to X::const_iterator, and then all those operations work by using that conversion.
That's incorrect. For example, if the operations are templated no implicit conversion will take place.
That's true, thanks, Dave. Reading it back I've also realised that the last sentence of mine that you quote is ambiguous. I didn't mean to suggest that the container requirements require that those operations use the conversion. The requirement is that X::iterator is convertible to X::const_iterator. The operations _could_ work by using that conversion, but aren't required to. jon -- "I was born not knowing and have had only a little time to change that here and there." - Feynman

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com...
| If someone would clearly and succinctly spell out the question, I'd be | happy to.
should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container?
There is no requirement that it be possible, and many early STL implementations failed to make it possible. It's generally regarded as a poor QOI that doesn't allow it. That capability is one of the things that iterator_facade and iterator_adaptor make easy. -- Dave Abrahams Boost Consulting www.boost-consulting.com

On Jun 15, 2005, at 11:58 AM, David Abrahams wrote:
"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"David Abrahams" <dave@boost-consulting.com> wrote in message news:uk6kws88y.fsf@boost-consulting.com...
| If someone would clearly and succinctly spell out the question, I'd be | happy to.
should one be able to add, subtract, and compare mutable random access iterators with random access const_iterators provided they point to the same container?
There is no requirement that it be possible, and many early STL implementations failed to make it possible. It's generally regarded as a poor QOI that doesn't allow it. That capability is one of the things that iterator_facade and iterator_adaptor make easy.
Umm... and you helped me with the wording to require this for C++0X (it is already in the WP): http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#179 -Howard

"Howard Hinnant" <hinnant@twcny.rr.com> wrote in message news:2c82a06f47cb364610ee3f054122873e@twcny.rr.com... | On Jun 15, 2005, at 11:58 AM, David Abrahams wrote: | | > "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > | >> "David Abrahams" <dave@boost-consulting.com> wrote in message | >> news:uk6kws88y.fsf@boost-consulting.com... | >> | >> | If someone would clearly and succinctly spell out the question, I'd | >> be | >> | happy to. | >> | >> should one be able to add, subtract, and compare mutable random access | >> iterators with | >> random access const_iterators provided they point to the same | >> container? | > | > There is no requirement that it be possible, and many early STL | > implementations failed to make it possible. It's generally regarded | > as a poor QOI that doesn't allow it. That capability is one of the | > things that iterator_facade and iterator_adaptor make easy. | | Umm... and you helped me with the wording to require this for C++0X (it | is already in the WP): | | http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#179 Thanks! I'm only missing to make operator- to be free-standing. I will update that as well. -Thorsten
participants (5)
-
Alexey Bakhvalov
-
David Abrahams
-
Howard Hinnant
-
Jonathan Wakely
-
Thorsten Ottosen