What is a clean/concise way to pass empty range to a function taking a pair of iterators?
c++, c++11, stl
Solution
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
Problem
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?