Ответ 1
Там есть маршрут свободной функции, но если вы также не обеспечиваете перегрузки для std::string
, это змеиная яма.
#include <string>
#include <string_view>
std::string_view sub_string(
std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
// this is fine and elegant...
auto bar = sub_string(source, 3);
// but uh-oh...
bar = sub_string("foobar"s, 3);
}
IMHO весь дизайн string_view - это шоу ужасов, которое вернет нас в мир segfaults и сердитых клиентов.
обновление:
Даже добавление перегрузок для std::string
- это шоу ужасов. Посмотрите, можете ли вы заметить тонкую временную память segfault...
#include <string>
#include <string_view>
std::string_view sub_string(std::string_view s,
std::size_t p,
std::size_t n = std::string_view::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string&& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
std::string sub_string(std::string const& s,
std::size_t p,
std::size_t n = std::string::npos)
{
return s.substr(p, n);
}
int main()
{
using namespace std::literals;
auto source = "foobar"s;
auto bar = sub_string(std::string_view(source), 3);
// but uh-oh...
bar = sub_string("foobar"s, 3);
}
Компилятор ничего не предупредил. Я уверен, что обзор кода тоже не будет.
Я уже говорил об этом раньше, и я скажу это снова, на случай, если кто-либо из комитета С++ будет смотреть, , позволяющий неявные преобразования от std::string
до std::string_view
- ужасная ошибка, которая будет только служить приведите С++ в дурную славу.
Update
Подняв это (для меня) довольно тревожное свойство string_view на доске объявлений cpporg, мои проблемы были удовлетворены безразличием.
Консенсус рекомендаций этой группы состоит в том, что std::string_view
никогда не должен возвращаться из функции, а это значит, что мое первое предложение выше - плохая форма.
Конечно, никакая компилятор не помогает ловить время, когда это происходит случайно (например, через расширение шаблона).
В результате std::string_view
следует использовать с максимальной осторожностью, потому что с точки зрения управления памятью это эквивалентно скопируемому указателю, указывающему на состояние другого объекта, который больше не может существовать. Однако он выглядит и ведет себя во всех других отношениях, таких как тип значения.
Таким образом, код выглядит следующим образом:
auto s = get_something().get_suffix();
Безопасен, когда get_suffix()
возвращает std::string
(по значению или ссылке)
но UB, если get_suffix() когда-либо реорганизован для возврата std::string_view
.
Что в моем скромном представлении означает, что любой код пользователя, в котором хранятся возвращенные строки с использованием auto
, будет разбит, если библиотеки, которые они вызывают, когда-либо реорганизованы, чтобы вернуть std::string_view
вместо std::string const&
.
Итак, отныне, по крайней мере для меня, "почти всегда авто" должен стать "почти всегда авто, кроме случаев, когда он строит".