c++ view c++1z c++17 stdstring

c++ - Cómo obtener eficientemente una `string_view` para una subcadena de` std:: string`



c++1z c++17 (3)

Usando http://en.cppreference.com/w/cpp/string/basic_string_view como referencia, no veo forma de hacerlo con más elegancia:

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

Peor aún, el enfoque ingenuo es una trampa y deja v una referencia pendiente a un temporal:

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

Parece que recuerdo algo como que podría haber una adición a la biblioteca estándar para devolver una subcadena como vista:

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

Puedo pensar en las siguientes soluciones:

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

Francamente, no creo que ninguno de estos sea muy agradable. En este momento, lo mejor que se me ocurre es usar alias para hacer las cosas menos detalladas.

using sv = std::string_view; sv(s).substr(6, 5);


Así es como puede crear eficientemente una subcadena string_view.

#include <string> inline std::string_view substr_view(const std::string &s,size_t from,size_t len) { if( from>=s.size() ) return {}; return std::string_view(s.data()+from,std::min(s.size()-from,len)); } #include <iostream> int main(void) { std::cout << substr_view("abcd",3,11) << "/n"; std::string s {"0123456789"}; std::cout << substr_view(s,3,2) << "/n"; return 0; }


Existe la ruta de función libre, pero a menos que también proporcione sobrecargas para std::string , es un pozo de serpientes.

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

En mi humilde opinión, todo el diseño de string_view es un espectáculo de terror que nos llevará de vuelta a un mundo de segfaults y clientes enojados.

actualizar:

Incluso agregar sobrecargas para std::string es un espectáculo de terror. Vea si puede detectar la bomba de tiempo sutil 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); }

El compilador no encontró nada de lo que advertir aquí. Estoy seguro de que tampoco una revisión de código.

Lo he dicho antes y lo diré nuevamente, en caso de que alguien en el comité de c ++ esté mirando, permitir conversiones implícitas de std::string a std::string_view es un error terrible que solo servirá para desprestigiar a c ++ .

Actualizar

Habiendo planteado esta (para mí) propiedad bastante alarmante de string_view en el tablero de mensajes de cpporg, mis preocupaciones se han encontrado con indiferencia.

El consenso de los consejos de este grupo es que std::string_view nunca debe devolverse de una función, lo que significa que mi primera oferta anterior es de mala forma.

Por supuesto, no hay ayuda del compilador para detectar los momentos en que esto ocurre por accidente (por ejemplo, mediante la expansión de la plantilla).

Como resultado, std::string_view debe usar con sumo cuidado, porque desde el punto de vista de la administración de memoria es equivalente a un puntero copiable que apunta al estado de otro objeto, que ya no existe. Sin embargo, se ve y se comporta en todos los demás aspectos como un tipo de valor.

Por lo tanto, código como este:

auto s = get_something().get_suffix();

Es seguro cuando get_suffix() devuelve un std::string (ya sea por valor o referencia)

pero es UB si get_suffix () alguna vez se refactoriza para devolver un std::string_view .

Lo que, en mi humilde opinión, significa que cualquier código de usuario que almacene cadenas devueltas usando auto se romperá si las bibliotecas a las que llaman alguna vez se refactorizan para devolver std::string_view en lugar de std::string const& .

Entonces, de ahora en adelante, al menos para mí, "casi siempre automático" tendrá que convertirse en "casi siempre automático, excepto cuando se trata de cadenas".


Puede usar el operador de conversión de std :: string a std :: string_view :

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