¿Cómo crear correctamente std::string desde un std::string_view?

3 minutos de lectura

Avatar de usuario de Leon
León

Tengo una clase:

class Symbol_t {
public:
   Symbol_t( const char* rawName ) {
      memcpy( m_V, rawName, 6 * sizeof( char ) );
   };

   string_view strVw() const {
      return string_view( m_V, 6 );
   };

private:
   char m_V[6];

}; // class Symbol_t

y hay una función lib que no puedo modificar:

extern bool loadData( const string& strSymbol );

Si hay una variable local:

Symbol_t   symbol( "123456" );

Cuando necesito llamar a loadData, no me atrevo a hacerlo así:

loadData( string( symbol.strVw().begin(), symbol.strVw().end() ) );

tengo que hacer asi:

string_view svwSym = symbol.strVw();
loadData( string( svw.begin(), svw.end() ) );

Mi pregunta: ¿Es correcto el primer método? o debo usar el segundo?

Porque creo que en el Método 1, los iteradores que pasé al constructor de std::string son de dos objetos String_vew diferentes y, en teoría, el resultado no está definido, aunque obtendríamos el resultado esperado con casi todos los compiladores de C++.

¡Cualquier sugerencia será apreciada! gracias.

StoryTeller - Avatar de usuario de Unslander Monica
StoryTeller – Unslander Mónica

No hay necesidad de usar el c’tor tomando un rango. std::string tiene un constructor que opera en términos de std::string_view, numero 10 en la lista. cuyo efecto es

template < class T >
explicit basic_string( const T& t, const Allocator& alloc = Allocator() ); 

Implícitamente convierte t en una vista de cadena sv como si fuera std::basic_string_view<CharT, Traits> sv = t;luego inicializa la cadena con el contenido de svcomo si por basic_string(sv.data(), sv.size(), alloc). Esta sobrecarga solo participa en la resolución de sobrecarga si std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>> es cierto y std::is_convertible_v<const T&, const CharT*> Es falso.

Como ambas condiciones se cumplen para std::string_view mismo, podemos escribir la llamada a loadData como simplemente:

loadData( std::string( symbol.strVw() ) );

Si tiene alguna vista de cadena en C++ que desea convertir a formato de cadena (para que pueda volver a una función después de realizar todos sus análisis, por ejemplo), puede realizar ese cambio haciendo esto:

string_view sv;
string s = {sv.begin(), sv.end()};

Yendo al revés, para obtener una vista de cadena de una cadena (para obtener un puntero a esa cadena), puede hacer esto:

string s;
string_view sv = string_view(s);

Tenga en cuenta que la subcadena y una variedad de otras operaciones se pueden realizar en string_view al igual que en la cadena.

  • Sin embargo, ¿esto no hace una copia completa de la cadena? El propósito principal de string_view es evitar hacer exactamente eso.

    – Roflcopter4

    22 de noviembre de 2022 a las 11:13

Avatar de usuario de Maxim Egorushkin
Maxim Egorushkin

¿Es correcto el primer método?

es, desde strVw devuelve idéntico string_views: todos apuntan a lo mismo m_V y tienen el mismo tamaño.

La corrección aquí depende de cómo strVw está implementado.

o debo usar el segundo?

Yo crearía una función de conversión:

inline std::string as_string(std::string_view v) { 
    return {v.data(), v.size()}; 
}

Y usa eso:

loadData(as_string(symbol.strVw()));

Este método es seguro independientemente de strVw implementación.

¿Ha sido útil esta solución?