¿Algún problema que reemplaza global const char [] con constexpr string_view?

17

Nuestro equipo está trabajando con una base de código C ++ de más de 10 años y recientemente se cambió a un compilador C ++ 17. Por lo tanto, estamos buscando formas de modernizar nuestro código. En una conferencia en YouTube escuché la sugerencia de reemplazar const char*cadenas globales con constexpr string_view.

Dado que tenemos un número considerable de tales const char*constantes de cadena global en nuestro código, quiero preguntar si hay problemas o posibles problemas que debemos tener en cuenta.

PixelSupreme
fuente

Respuestas:

15

Vale la pena tener en cuenta estos problemas:

  1. std::string_viewno necesita ser nullterminado. Entonces, si reemplaza algunos const char*por string_viewy reemplaza la construcción de una subcadena previamente nullterminada char*por una string_viewvía std::string_view::substr, no puede pasar el puntero subyacente a una API que espera una nullcadena terminada. Ejemplo (sin UB, pero que también es fácilmente construible):

    void legacy(const char *str) {
       std::printf("%s\n", str);
    }
    
    constexpr std::string_view sv1 = "abcde";
    constexpr std::string_view sv2 = sv1.substr(0, 2); // view on "ab"
    
    legacy(sv2.data()); // Not intended: prints "abcde" 
  2. Si bien puedes construir implícitamente a std::stringdesde a const char*, no puedes hacerlo con a std::string_view. La idea es que no se realice una copia profunda debajo de la cubierta, sino solo cuando se solicite explícitamente. Ejemplo:

    std::map<std::string, int> m;
    constexpr std::string_view sv = "somekey";
    constexpr const char *old = "somekey";
    
    m[old] = 42; // works as expected
    m[sv] = 42; // fails to compile
    m[std::string(sv)] = 42; // be explicit, this is ok

    Dependiendo del uso existente de las const char*instancias globales en su proyecto, este comportamiento puede requerir intervención manual en varios lugares.

lubgr
fuente
que la terminación distinta de cero es definitivamente un problema. Ahora necesito revisar nuestros SV. ¿Supongo que lo harías en std::string(sv).c_str()lugar de pasar a la API?
Darune
@darune Esa es una opción, pero entonces los supuestos de por vida de la API deben ser verificados, ¿verdad? Si vas con someLegacyFct(std::string(sv).c_str())y esto de alguna manera back-end almacena el puntero ...
lubgr
eso es correcto - sólo con la suposición de que toda la vida
darune
El segundo problema es que "por suerte" no será un gran problema para nosotros. El marco de nuestra empresa tiene su propia clase de cadena (lo sé ...), con un const char*constructor explícito . Por lo tanto, la construcción explícita de std::stringfrom string_viewsería coherente en nuestro caso.
PixelSupreme