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?

3 Answers 3

8

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

Comments

1

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.

7 Comments

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.
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. :)
@DavidRodríguez-dribeas "(an) implementation of a list iterator could be a pointer into the node, with null identifying one past the end (which is a common idiom) " could you cite even one such broken std::list implementation?
@Artem "commercial-grade compilers would be a little more clever about it. " Indeed, commercial-grade compilers should assert in this case.
@curiousguy: Well, not exactly a null pointer, but the implementation of forward_list in C++11 in GCC 4.6 uses an iterator that is a class holding a pointer into the node, with end being defined as iterator end() { return iterator(0); }, which means that in a forward_list, in that particular implementation the end iterators from two separate containers will compare equal.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.