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

+3


source to share


2 answers


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.

+9


source


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

      

-2


source







All Articles