Получить индекс в векторе от обратного итератора

Я знаю, как получить индекс из векторного итератора, вычитая из него начальный итератор. Например:

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

11

Решение

Я хотел бы использовать:

#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]так что в конечном итоге вам также понадобится проверка против этого.

9

Другие решения

Вы можете использовать:

container.size() - 1 - (iterator - container.rbegin())

или же

container.size() - 1 - std::distance(container.rbegin(), iterator)

Подробнее о обратных итераторах. Как использовать обратные итераторы без путаницы. Для преобразования обратных итераторов в прямые итераторы и многое другое.

1

По вопросам рекламы [email protected]