Convert rend iterator to end iterator
This is not a duplicate of how to convert reverse_iterator
to iterator
, because I want the result to be different from the normal conversion.
Given only reverse_iterator
which one is returned from rend
, is it possible to convert it to the corresponding iterator
one that will be returned from end
?
for example
std::vector<int> myvec = {...};
auto rit = myvec.rend();
auto it = MAGIC(rit);
it == myvec.end(); // true
If it is not possible to do this with only consideration reverse_iterator
, what is the minimum information required to do this? (So I can look at workarounds.)
source to share
Short answer: No.
An iterator refers to a single point in a container without having actual knowledge of the container itself. The iterators returned by end()
and rend()
point to different ends of the container, i.e. There may be some or many elements between the points they refer to, regardless of the reverse nature of one of the iterators. Thus, without knowing about the container itself, or at least its size, there is no way to get from one end of the container to the other, and since iterators do not have this knowledge, there is no way to get from rend()
to end()
, from end()
to begin()
, etc. without further information.
The minimum information required is the size of the "gap" between the two points. With this and the normal conversion between backward and no backward iterators, it's an easy task:
auto rend = v.rend();
auto begin = rend.base();
assert(begin == v.begin());
auto end = begin + v.size(); //the size is the key!
assert(end == v.end());
But, since you cannot get the size from reverse_iterator
, but only from, the container itself, you can easily request it end()
in the first place.
source to share
Expression
myvec.rend().base()
equivalent to
myvec.begin()
Here is a demo example
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
std::vector<int>::iterator it = v.rend().base();
std::cout << *it << std::endl;
return 0;
}
Output signal
1
Another demo that shows the relationship between std::vector<int>::iterator
and std::vector<int>::reverse_iterator
(instead of the templetae argument, int
you can use any type T
>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
if ( v.begin() == v.rend().base() )
{
std::cout << "v.begin() == v.rend().base()" << std::endl;
}
if ( v.end() == v.rbegin().base() )
{
std::cout << "v.end() == v.rbegin().base()" << std::endl;
}
return 0;
}
Output signal
v.begin() == v.rend().base()
v.end() == v.rbegin().base()
source to share