I always thought that a "singular" iterator was one that has been default-initialised, and these could serve as comparable sentinel values of sorts:
typedef std::vector<Elem>::iterator I;
I start = I();
std::vector<Elem> container = foo();
for (I it = container.begin(), end = container.end(); it != end; ++it) {
if ((start == I()) && bar(it)) {
// Does something only the first time bar(it) is satisfied
// ...
start = it;
}
}
But this answer suggests not only that my definition of "singular" is wrong, but also that my comparison above is totally illegal.
Is it?
Obviously this will work for some iterators - T*
being a clear example - but it's definitely not guaranteed correct behavior for all iterators. C++11 24.2.1 [iterator.requirements.general] p5:
Singular values are not associated with any sequence ... Results of most expressions are undefined for singular values; the only
exceptions are destroying an iterator that holds a singular value, the
assignment of a non-singular value to an iterator that holds a
singular value, and, for iterators that satisfy the
DefaultConstructible requirements, using a value-initialized iterator
as the source of a copy or move operation.
You can replicate your desired behavior with a simple bool
flag:
std::vector<Elem> container = foo();
bool did_it_already = false;
for (I it = container.begin(), end = container.end(); it != end; ++it) {
if (!did_it_already && bar(it)) {
// Does something only the first time bar(it) is satisfied
// ...
did_it_already = true;
}
}