Почему std::string
имеет функцию члена find
, а std::vector
, а друзья не имеют ее?
Что-то не так с использованием std::find
в строке?
Почему std::string
имеет функцию члена find
, а std::vector
, а друзья не имеют ее?
Что-то не так с использованием std::find
в строке?
Это в основном по историческим причинам, но не только.
Строковая библиотека и STL (которая представляет собой библиотеку контейнеров/алгоритмов, разработанную А. Степановым, которая в итоге стала частью стандартной библиотеки С++) были разработаны независимо, и они приняли различные соглашения.
Однако, поскольку они в конечном итоге оба конвертируются в стандартную библиотеку С++, С++ Standard делает попытку унифицировать эти синтаксические соглашения и позволяет использовать string
с алгоритмами STL, поэтому класс string
имеет функции-члены, такие как begin()
и end()
помимо других функций-членов, таких как substr()
.
Помимо обратной совместимости, в любом случае есть еще одна причина, по которой string
предоставляет функции-члены, такие как find()
: в отличие от контейнеров, которые предназначены для работы с универсальными алгоритмами, которые обеспечивают доступ к элементам или манипулируют ими, строки в основном рассматриваются как сами ценности, а не как совокупности значений (т.е. последовательности char
s). Таким образом, имеет смысл инкапсулировать алгоритмы, которые управляют значениями string
в функции-члены класса string
.
В своем дизайне стандартная библиотека С++ поддерживает оба этих представления string
s: как коллекции значений и самих значений.
UPDATE:
Бит вашего первого предложения "пока std::vector
и друзья его не имеют" не совсем правильно. По крайней мере, если вы расширяете диапазон друзей std::vector
до std::set
, std::multiset
, std::map
, std::multimap
, std::unordered_set
и std::unordered_map
(другими словами, в значительной степени для всех ассоциативных контейнеры в стандартной библиотеке С++).
У некоторых структур данных действительно есть версия функций некоторых общих STL-алгоритмов на их интерфейсе: это либо указывает на то, что эти алгоритмы имеют более эффективную реализацию, чем их общие экземпляры для этих конкретных структур данных (например, find()
) или что требуется специализированная реализация, поскольку общие алгоритмы вообще не могут применяться к этим структурам данных (например, std::remove()
, который изменяет значения в контейнере).
Семантика std::string::find
(*) полностью отличается от семантики std::find
. В случае алгоритма он найдет элемент внутри контейнера, который, если вы примените к std::string
, означает поиск местоположения, для которого символ X.
Функции-члены std::string::find
(кроме одного варианта, который принимает один charT
), имеют другую цель, они находят подстроки (т.е. последовательность значений, а не одно значение).
Следующий вопрос будет заключаться в том, почему такая перегрузка, которая принимает charT
, есть, когда это может быть просто вызов std::find
. Как заметил Энди в своем ответе, реализация STL и библиотек строк происходила отдельно. Итераторы затем добавлялись к компоненту std::string
. К тому времени, когда итераторы были добавлены в std::string
, эта перегрузка уже была там, даже если это не так, семантика все еще немного отличается от std::find
тем, что, как и в остальной части std::string::find
, вместо итераторов они принимать и возвращать позиции. Это не означает, что нельзя реализовать в терминах другого, только этот код будет более запутанным.
(*) Возьмите меня... прочитайте std::string
, как если бы это было написано std::basic_string<>