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