I have a function that takes a pair of iterators. I'd like to provide a no-argument version of the function that behaves as if it had been passed an empty range.
To be concrete, let's say the first function is:
void f(vector<int>::iterator b, vector<int>::iterator e) { // impl. }
I'd like to write this:
void f() { f({}, {}); }
Do I have the initialisation correct here, the {}, {} should be two default constructed vector::iterator types? (It compiles).
Do I have to construct a container to get a pair of iterators that compare equal?
In my understanding this cannot be done generally in a standard conforming way.
24.2.1/5:
Iterators can also have singular values that are not associated with any sequence. [ Example: After the declaration of an uninitialized pointer x (as with int* x;), x must always be assumed to have a singular value of a pointer. — end example ] 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. [ Note: This guarantee is not offered for default initialization, although the distinction only matters for types with trivial default constructors such as pointers or aggregates holding pointers. — end note ] In these cases the singular value is overwritten the same way as any other value. Dereferenceable values are always non-singular.
Default/value initialisation clearly isn't associated with any sequence, so the Iterator is singular. Comparing two singular Iterators is undefined behaviour.
std::vector<int>::iterator i;
std::vector<int>::iterator j = i; // UB, assignment of a non-a singular value
// If you pass `i` to a function, a copy is done
// which also results in UB (as in Andy's answer).
Next try, use value-initialisation
std::vector<int>::iterator i{};
std::vector<int>::iterator j = i; // ok, i is value-initialized
i == j; // undefined, comparison is not explicitly non-undefined behavour
i == i; // undefined, comparison is not explicitly non-undefined behavour
Since we don't have more information about vector<int>::iterator
, your approach is wrong.
What you can do is changing your f
to a template and use a pointer:
template <typename Iter>
void f(Iter b, Iter e);
int *p; f(p, p); // ok, defined for pointers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With