简体   繁体   中英

C++ value initialized vector iterator comparison

Is the following code legal in c++17?

std::vector<int> x{1,2,3};
std::vector<int>::iterator it{};
bool result = x.begin() != it;

The following is quoted from https://en.cppreference.com/w/cpp/named_req/ForwardIterator :

Equality and inequality comparison is defined over all iterators for the same underlying sequence and the value initialized-iterators

If I understand this correctly, the comparison should be ok. And it seems to work on clang and gcc, but when I run this with MSVC 2019 in debug mode, I get an assert saying "vector iterators incompatible".

I'm not asking about the outcome of the comparison, I'm only interested if MSVC is conforming to the standard here.

Live example on godbolt

MSVC is conforming.

Only iterators to the same sequence may generally be compared with one another. Value initialised iterators are considered to be iterators to the same empty sequence. That "virtual" empty sequence is distinct from any other sequence, and comparisons across separate sequences are not (required to be) defined, and thus the example is potentially undefined.

Standard quote (latest draft)

[forward.iterators] The domain of == for forward iterators is that of iterators over the same underlying sequence. However, value-initialized iterators may be compared and shall compare equal to other value-initialized iterators of the same type. [ Note: Value-initialized iterators behave as if they refer past the end of the same empty sequence. — end note

Vector iterators are not guaranteed to implement the comparison for a wider domain than this. If it doesn't, then the behaviour is undefined. Your comparison is outside of this domain.

Visual Studio is correct. You are getting an assertion (in debug only!) because your code has undefined behaviour , and the implementation is warning you about that.

Value-initialised iterators can only be compared to other value-initialised iterators. This is a generalisation of the rule that comparing pointers or iterators only works within a sequence or array (with one notable exception being std::less , which handily provides a total ordering over the whole memory space; this is the only way a set, using the default comparator, of unrelated pointers can work).

[forward.iterators] The domain of == for forward iterators is that of iterators over the same underlying sequence. However, value-initialized iterators may be compared and shall compare equal to other value-initialized iterators of the same type. [ Note: Value-initialized iterators behave as if they refer past the end of the same empty sequence. — end note ]

No semantics are defined for an ordering between a value-initialised iterator, and an iterator to a position in a sequence.

The cppreference text is a little badly-worded in this regard, though the same page does do a little better on the semantics for a successful equality between two singular iterators:

A value-initialized LegacyForwardIterator behaves like the past-the-end iterator of some unspecified empty container: it compares equal to all value-initialized LegacyForwardIterators of the same type.

And, again, you cannot compare iterators to different containers, so there we have our rule.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM