STL алгоритмы и const_iterators - PullRequest
       43

STL алгоритмы и const_iterators

4 голосов
/ 27 октября 2009

Сегодня я написал небольшой предикат для поиска подходящих символов в контейнере.

Но я столкнулся с проблемой: я хочу использовать этот предикат в вызове std::find_if внутри const-метода класса, ища в контейнере, который является членом этого класса.

Но я только что заметил, что ни std::find, ни std::find_if не могут работать на const_iterators!

Я проверил некоторые ссылки на C ++, и, похоже, нет версии std::find или std::find_if, которая принимает / возвращает const_iterators. Я просто не могу понять, почему, поскольку из того, что я видел, эти алгоритмы не могли изменить объект, на который ссылается итератор.

Вот как задокументировано std::find в реализации SGI:

Возвращает первый итератор i в диапазон [первый, последний) такой, что * i == значение. Возвращает последний, если нет такого итератор существует.

Ответы [ 5 ]

15 голосов
/ 27 октября 2009

std::find и std::find_if могут определенно работать на *::const_iterator для данного контейнера. Вы случайно не смотрите на сигнатуры этих функций и не понимаете их?

template <class InputIterator, class Type>
InputIterator find(InputIterator first, InputIterator last, const Type& val);

Обратите внимание, что InputIterator - это просто имя параметра типа шаблона, и любой const_iterator удовлетворяет требованиям для него.

Или, возможно, вы путаете const_iterator (т.е. итератор, ссылающийся на значение const) с const итератором (то есть итератором, который сам по себе const)?

5 голосов
/ 27 октября 2009

std::find и std::find_if оба принимают тип итератора как параметр шаблона, поэтому они, безусловно, могут работать на const_iterators. Просто для быстрого примера:

#include <vector>
#include <algorithm>
#include <iostream>
int main() { 
    std::vector<int> x;

    std::fill_n(std::back_inserter(x), 20, 2);
    x.push_back(3);

    std::vector<int>::const_iterator b = x.begin();
    std::vector<int>::const_iterator e = x.end();

    std::vector<int>::const_iterator p = std::find(b, e, 3);

    std::cout << *p << " found at position: " << std::distance(b, p) << "\n";
    return 0;
}

Это должно быть принято любым правильно работающим компилятором C ++ и выдает такие результаты, как:

3 найдено в позиции: 20

1 голос
/ 10 марта 2016

Если вы случайно оказались здесь по той же причине, что и я:

error: no matching function for call to ‘find(std::vector<int>::const_iterator, std::vector<int>::const_iterator, int)’

Это не имеет ничего общего с const_iterator с. Вы, вероятно, просто забыли #include <algorithm>: -)

1 голос
/ 23 декабря 2009

У меня только что была такая же проблема. У меня была функция-член, которая вызывала find_if для вектора-члена, и компилятор выдал мне ошибку, когда я попытался сделать функцию-член const. Оказалось, что это потому, что я присваивал возвращаемое значение find_if iterator вместо const_iterator. Это заставило компилятор предположить, что параметры find_if также должны быть iterator вместо const_iterator, что не удалось получить из вектора const.

0 голосов
/ 15 апреля 2016

У меня только что возникла проблема с этим кодом:

std::string str;
std::string::const_iterator start = str.begin();
std::string::const_iterator match = std::find(start, str.end(), 'x');

Ошибка: «нет соответствующей перегрузки для std :: find».

Исправление мне нужно было использовать cend (). Это сбивает с толку, что cbegin () не требуется, я не уверен, почему это преобразование нормально (неявно), а не для end () как параметр функции.

...