У нас есть несколько средних и крупных программных проектов, ориентированных на разные платформы (arm32/64 и x86/amd64 на Linux и Windows), в которых много дублирующегося кода, так как у каждого проекта есть свои split(string, delimiter)
, find_files(regex/pattern)
и тому подобное.
Из-за этого мы снова и снова исправляем одинаковые ошибки в разных проектах и тратим время на придумывание очередного варианта в следующем проекте. Поэтому я работаю над небольшими, "независимыми" от платформы библиотеками только для таких полезных функций, как эти (строка, сокеты, файловая система, время, ...).
Теперь к самой проблеме.
В настоящее время библиотека string предоставляет множество функций, принимающих std::string
в качестве параметров и возвращающих std::string
(или контейнеры, содержащие их).
Я хотел бы заменить их на std::string_view там, где это необходимо. Но я не уверен, где это будет уместно и как это сделать.
Функции типа
std::vector<std::string> split(const std::string& str, char delimiter);
могут быть
std::vector<std::string_view> split(std::string_view str, char delimiter);
Параметр std::string_view
здесь имеет смысл, но возвращаемый тип заставит вызывающие стороны обрабатывать его по-разному, что усложнит задачу, если вызывающая сторона захочет сохранить результаты (т.е. ей понадобится std::string).
Имеет ли смысл предоставлять несколько вариантов типа
std::vector<std::string> split(std::string_view str, char delimiter);
std::vector<std::string_view> split_v(std::string_view str, char delimiter);
?
Что должно быть по умолчанию? (т.е. будет ли более логичным, если split
возвращает string_view
, а split_s
возвращает string
?). Или есть совершенно другой способ? Какой подход был бы хорошим в целом, как с точки зрения производительности, так и простоты использования (и, следовательно, принятия), а также затруднения злоупотребления?
В C++ и его стандартных библиотеках вы найдете множество "строкоподобных" типов, таких как std::string
, std::string_view
, std::wstring
, char *
, std::string_view
и так далее. Эта старая запись в блоге от 2008 года уже упоминала 30 типов (в контексте Windows legacy, но без std::vector<std::string_view>
, который является C++17). Я уверен, что с тех пор это число увеличилось в несколько раз.
Как это поможет нам решить вашу проблему? Ну, в ситуации с огромным количеством доступных типов строк, я думаю, что при проектировании функций общего назначения лучше всего сосредоточиться только на одном типе, до тех пор пока
Поэтому я бы рекомендовал начать с _sv
в качестве возвращаемого типа.
Это дает вызывающей стороне свободу в явном преобразовании к другому строкоподобному типу, или нет, или позволяет добавить дополнительную вспомогательную функцию (функции). Для них дополнительное дополнение, дополнительный суффикс типа _strview
или std::string
должен быть абсолютно приемлемым для имени дополнительных функций.
Конечно, когда выяснится, что в вашей системе конкретный вариант "split-stringview-with-conversion-to-string" нужен тысячу раз, а "split-stringview-without-conversion" нет нигде во всей кодовой базе, вы можете принять другое решение.