to give context i'm trying to re-implement vector
container, and while reading about it's iterator
system requirements, i've stumbled upon this requirement from cplusplus reference:
can be incremented (if in a dereferenceable state ). the result is either dereferenceable or past-the-end iterator.
EX: a , a , *a
i've already overloaded the increment
and dereference
operators as so:
class iterator {
...
inline iterator& operator () {
_ptr;
return *this;
};
inline iterator operator (int) {
iterator tmp(*this);
operator ();
return (tmp);
};
inline reference operator*() const {
return _ptr;
};
...
}
i've researched a bit about this requirement and didn't found any informations mentioning this property, so i assumed it's irrelevant and handled by default by the compiler as long as i overload the operators separately, is that the case or should i implement my iterator in a way so that it can be incremented in a dereferenceable state.
CodePudding user response:
You cannot increment an end iterator, it is not dereferenceable. You cannot increment an invalid iterator, it is not dereferenceable.
Preconditions do not necessarily mean that you have to do something extra. They only give information when some operation, here increment, is defined.
For example
std::vector<int> foo;
auto it = foo.end();
it; // undefined
Incrementing the end iterator is undefined.
When a user calls your operator
on an invalid iterator (and then try to dereference it) it is their fault. They broke the contract.
For analogy consider a function:
int div(int a,int b) { return a/b; }
And specification states: "You can only call the function with b!=0
". The function does not need to check b!=0
, because if a user calls it with b==0
they broke the contract.
In a debug build you might want to add some convenience and check if preconditions hold before actually incrementing the iterator. Though in a release build this would incur unnecessary cost and be a nuisance for anybody who only increments dereferencable iterators (as they should).