Как эффективно получить "строковое представление" для подстроки " std:: string`


используя http://en.cppreference.com/w/cpp/string/basic_string_view в качестве ссылки, я не вижу способа сделать это более элегантно:

std::string s = "hello world!";
std::string_view v = s;
v = v.substr(6, 5); // "world"

хуже того, наивный подход является ловушкой и оставляет v висячая ссылка на временное:

std::string s = "hello world!";
std::string_view v(s.substr(6, 5)); // OOPS!

Я помню что-то вроде того, что может быть добавлено в стандартную библиотеку для возврата подстроки в виде представления:

auto v(s.substr_view(6, 5));

Я могу думать о следующих обходные пути:

std::string_view(s).substr(6, 5);
std::string_view(s.data()+6, 5);
// or even "worse":
std::string_view(s).remove_prefix(6).remove_suffix(1);

честно говоря, я не думаю, что это очень приятно. Сейчас самое лучшее, что я могу придумать, это использовать псевдонимы, чтобы просто сделать вещи менее подробными.

using sv = std::string_view;
sv(s).substr(6, 5);
2   52   2017-09-04 10:33:21

2 ответа:

есть маршрут свободной функции, но если вы также не предоставляете перегрузки для 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 - это шоу ужасов. Смотрите, если вы можете заметить тонкие бомбу замедленного действия, обработка выхода онлайн / оффлайн...

#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);
}

компилятор не нашел здесь ничего, о чем можно было бы предупредить. Я уверен, что обзор кода тоже не будет.

я уже говорил это раньше, и я скажу это снова, если кто-нибудь из комитета c++ смотрит,разрешение неявных преобразований из std::string до 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&.

так что отныне, по крайней мере для меня, "почти всегда авто" должно будет стать "почти всегда авто, за исключением случаев, когда это строки".

вы можете использовать оператор преобразования от std:: string до std:: string_view:

std::string s = "hello world!";
std::string_view v = std::string_view(s).substr(6, 5);