Існує безкоштовний функціональний маршрут, але якщо ви також не надаєте перевантажень 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;
auto bar = sub_string(source, 3);
bar = sub_string("foobar"s, 3);
}
IMHO - весь дизайн string_view - це шоу жахів, яке поверне нас у світ сегментальних розладів та розлючених клієнтів.
оновлення:
Навіть додавання перевантажень 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);
}
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);
bar = sub_string("foobar"s, 3);
}
Тут компілятор не знайшов про що попередити. Я впевнений, що перегляд коду теж не зробив би.
Я вже говорив це і повторю ще раз, на випадок, якщо хтось із комітету c ++ спостерігає, дозволяючи неявні перетворення з std::string
to std::string_view
є жахливою помилкою, яка буде служити лише для того, щоб привести c ++ на непристойність .
Оновлення
Піднявши цю (для мене) досить тривожну властивість string_view на дошці повідомлень cpporg, мої занепокоєння зустріли байдуже.
Консенсус-порада цієї групи полягає в тому, що std::string_view
ніколи не слід повертати функцію, а це означає, що моя перша пропозиція вище - погана форма.
Звичайно, немає допомоги компілятора, щоб вловити випадки, коли це трапляється випадково (наприклад, через розширення шаблону).
Як результат, std::string_view
слід використовувати з максимальною обережністю, оскільки з точки зору управління пам’яттю це еквівалентно копіюваному вказівнику, що вказує на стан іншого об’єкта, який може більше не існувати. Однак він виглядає і поводиться у всьому іншому, як тип значення.
Таким чином, код такий:
auto s = get_something().get_suffix();
Безпечно, коли get_suffix()
повертає a std::string
(або за значенням, або за посиланням)
але є UB, якщо функція get_suffix () коли-небудь реконструйована, щоб повернути a std::string_view
.
Що, на мій скромний погляд, означає, що будь-який користувацький код, що зберігає повернуті рядки, auto
буде зламаний, якщо бібліотеки, які вони викликають, коли-небудь рефактовані, щоб повернутися std::string_view
замість std::string const&
.
Тож відтепер, принаймні для мене, "майже завжди авто" доведеться стати, "майже завжди авто, крім випадків, коли це рядки".
string_view(s).substr(...)
), здається приємнішим, ніж одна функція, яка робить дві речі одночасно (.substr_view(...)
), навіть якщо вона існувала.