Найти индекс итератора в контейнере STL - нужна функция шаблона - PullRequest
3 голосов
/ 28 октября 2011

Я хочу иметь функцию с интерфейсом, подобным следующему:

template<typename T, typename R> int find_index (const T& list, const R& value);

Как я знаю, в STL есть find(), который возвращает итератор.Мне нужно вернуть индекс итератора (даже для неиндексированных контейнеров, таких как std::list).Я попробовал этот код:

template<typename T, typename R>
int find_index (const T& list, const R& value)
{
    int index = 0;
    for (T::const_iterator it = list.begin(); it != list.end(); it++, index++)
        if ((*it) == value)
            return index;
    return -1;
}

Но компилятор показывает ошибку на it - похоже, ему не разрешено получать const_iterator из шаблонного имени типа.Могу ли я обойти это?

В худшем случае я могу передать начало и конец итераторов в аргументы find_index, но это выглядит не так хорошо.Был бы благодарен за элегантное решение.

1 Ответ

11 голосов
/ 28 октября 2011
for (typename T::const_iterator it = list.begin(); it != list.end(); ++it, ++index)

должен решить вашу проблему.

При использовании зависимых типов (типов в зависимости от параметров шаблона) компилятор не знает, что const_iterator является типом, пока он не создает экземпляр шаблона с конкретным типом, он также может быть просто статической переменной или чем-то еще. Используя ключевое слово typename, вы говорите ему, что const_iterator действительно тип.

В C ++ 11 вы также можете обойти всю проблему typename, используя ключевое слово auto:

for (auto it = list.begin(); it != list.end(); ++it, ++index)

Если у вас уже есть итератор (возможно, из какой-то другой операции), вы также можете просто вычислить расстояние от начала списка до этого итератора:

#include <iterator>

int index = std::distance(list.begin(), it);

Но поскольку это имеет линейную сложность для std::list, лучше использовать самодельную функцию find_index, чем std::find, а затем std::distance, по крайней мере с точки зрения производительности.

...