Home > Software design >  How to overload an iterator so it can be incremented in a dereferenceable state?
How to overload an iterator so it can be incremented in a dereferenceable state?

Time:09-27

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).

  • Related