tags:

views:

104

answers:

3
list<int> foo;
list<int> foo2;
list<int>::iterator foo_end = foo.end();
list<int>::iterator foo2_end = foo2.end();

for (list<int>::iterator it = foo.begin(); it != foo2_end; ++foo) <- notice != comparison here
{
   ...

it this allowed? will it work correctly.

I am inclined to think that this is implementation dependent, anyone knows if standard says anything about this?

+2  A: 

Yes it is allowed (i.e. will compile).
No it will not work correctly.

foo2_end points to the end of foo2, not foo, so your iterator will start at the start of foo and end when it reaches the end of foo2, which will be never, because you are iterating foo. Once it iterates past the end of foo you will get a seg-fault.

Note: I assumed that you meant to write ++it, not ++foo.

Peter Alexander
+1  A: 

It will compile but result in a seg fault. The iterators are object-specific, and comparing two iterators from different objects will always yield an inequality. So the it != foo2_end expression will always evaluate to true, and your program will crash when it reaches foo.end() and you attempt to dereference it.

Artem
That depends on the implementation of the iterators. A trivial, and not really good, implementation of a list iterator could be a pointer into the node, with null identifying one past the end (which is a common idiom) [maybe a pointer into the list is required for some operation], with equality being defined as a direct comparison of the referred node addresses. There is nothing in the standard that would make that implementation non-conforming.
David Rodríguez - dribeas
Fair enough, though I presume commercial-grade compilers would be a little more clever about it. After all, making interfaces easy to use correctly and hard to use incorrectly is a good, common goal. :)
Artem
+7  A: 

There was a defect reported about this (LWG defect 446). The defect report asked whether it is valid to compare iterators that refer to elements of different containers.

Notes in the defect report explain that it was certainly the intention that doing so is undefined, but it is not explicitly stated that it is undefined.

The proposed resolution was to add the following to the standard, explicitly stating that it is undefined:

The result of directly or indirectly evaluating any comparison function or the binary - operator with two iterator values as arguments that were obtained from two different ranges r1 and r2 (including their past-the-end values) which are not subranges of one common range is undefined, unless explicitly described otherwise.

Edit: That language is not included in the C++0x FCD. This issue was in fact resolved by changes in N3066; specifically the following addition (§24.2.5/2):

The domain of == for forward iterators is that of iterators over the same underlying sequence.

James McNellis