Search code examples
c++iteratorlistiterator

Reseat the container an iterator "points" to


Suppose I have a std::list myList and an iterator myIt that I am using to point to some element of the list.

Now I make a shallow copy copiedList of myList (so I can reorder it). Similarly I can make a copy copiedIt of myIt, however it still references myList instead of copiedList, meaning I cannot sensibly compare it against copiedList.end(), as I may have modified that list.

Is there a (standard) way to reseat copiedIt to reference copiedList instead? This should be semantically valid, as long as I have not made any changes to the copy.

My current solution is to use the original iterator to std::find the pointed-to element in the copy of the list, but while that works and causes no problems, it seems unelegant.


Solution

  • You can use std::next and std::distance, like this:

    template <class Container>
    typename Container::iterator reseat(typename Container::iterator it, const Container &source, Container &target)
    {
      return std::next(target.begin(), std::distance(source.begin(), it));
    }
    

    In prose: find the distance of it from the beginning of its container, and take an iterator to the same-distant element in the new container.

    This could easily be generalised to allow source and target to be of different types. With slightly more work, generalisation to constant iterators is also possible.