Я знаю, как получить индекс из векторного итератора, вычитая из него начальный итератор. Например:
vector<int>::iterator it = find(vec.begin(), vec.end(), x);
size_t position = it - vec.begin();
Однако теперь я хочу найти индекс последнего x
в векторе. Как я могу получить реальный индекс от обратных итераторов? Я нашел следующее, что, кажется, работает (правка: это не так), но, возможно, есть лучший (более идиоматический или что-то еще …) способ.
vector<int>::reverse_iterator it = find(vec.rbegin(), vec.rend(), x);
size_t position = vec.size() - (it - vec.rbegin());
Я хотел бы использовать:
#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!";
}
Причина для -1
в вычислении расстояния из-за преобразования между обратными и регулярными итераторами в .base()
член:
24.5.1 Обратные итераторы [reverse.iterators]
1 Шаблон класса reverse_iterator — это адаптер итератора, который выполняет итерацию
от конца последовательности, определенной его итератором, до
начало этой последовательности. Принципиальная связь между реверсом
итератор и соответствующий ему итератор i устанавливается
идентичность:&*(reverse_iterator(i)) == &*(i - 1)
,
Заметка: Вы также можете использовать приведенный выше код без проверки v.rend()
и использовать соглашение, которое idx == -1
эквивалентно элементу, который не найден. Тем не менее, это теряет способность делать v[idx]
так что в конечном итоге вам также понадобится проверка против этого.
Вы можете использовать:
container.size() - 1 - (iterator - container.rbegin())
или же
container.size() - 1 - std::distance(container.rbegin(), iterator)
Подробнее о обратных итераторах. Как использовать обратные итераторы без путаницы. Для преобразования обратных итераторов в прямые итераторы и многое другое.