Get index in vector from reverse iterator
I would use:
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
auto v = std::vector<int> { 1, 2, 3 };
auto rit = std::find(v.rbegin(), v.rend(), 3);
if (rit != v.rend()) {
auto idx = std::distance(begin(v), rit.base()) - 1;
std::cout << idx;
} else
std::cout << "not found!";
}
Live Example.
The reason for the -1
in the distance computation is because of the conversion between reverse and regular iterators in the .base()
member:
24.5.1 Reverse iterators [reverse.iterators]
1 Class template reverse_iterator is an iterator adaptor that iterates from the end of the sequence defined by its underlying iterator to the beginning of that sequence. The fundamental relation between a reverse iterator and its corresponding iterator i is established by the identity:
&*(reverse_iterator(i)) == &*(i - 1)
.
Note: you could also use the above code without the check for v.rend()
, and use the convention that idx == -1
is equivalent to an element that is not found. However, that loses the ability to do v[idx]
, so eventually you would need a check against that as well.
You could use:
container.size() - 1 - (iterator - container.rbegin())
or
container.size() - 1 - std::distance(container.rbegin(), iterator)
More info about reverse iterators. How To Use Reverse Iterators Without Getting Confused. To convert reverse iterators into forward iterators and much more.
I would change TemplateRex's answer to use only reverse iterators, thus avoiding any headache with reverse-forward conversions.
int main()
{
auto v = std::vector<int> { 1, 2, 3 };
auto rit = std::find(v.rbegin(), v.rend(), 3);
if (rit != v.rend()) {
auto idx = std::distance(rit, v.rend()) - 1;
std::cout << idx;
} else
std::cout << "not found!";
}
The -1
is still needed because the first element of the vector (index 0) is actually at v.rend() - 1
.