Alguma dica substituindo o const global char [] por constexpr string_view?

17

Nossa equipe está trabalhando com uma base de código C ++ com mais de 10 anos e recentemente mudou para um compilador C ++ 17. Então, estamos procurando maneiras de modernizar nosso código. Em uma conferência no YouTube, ouvi a sugestão de substituir const char*as cordas globais por constexpr string_view.

Como temos um número considerável dessas const char*constantes globais de string em nosso código, quero perguntar se há alguma dica ou problema em potencial que precisamos estar cientes?

PixelSupreme
fonte

Respostas:

15

Vale a pena conhecer esses problemas:

  1. std::string_viewnão precisa ser nullterminado. Portanto, se você substituir alguns const char*por string_viewe substituir a construção de uma substring anteriormente nullterminada char*por uma string_viewvia std::string_view::substr, não poderá passar o ponteiro subjacente para uma API que espera uma nullstring terminada. Exemplo (sem UB, mas que também é facilmente construtível):

    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. Enquanto você pode implicitamente construir a std::stringpartir de a const char*, você não pode fazer isso com a std::string_view. A idéia é que uma cópia detalhada não ocorra de forma oculta, mas apenas quando solicitada explicitamente. Exemplo:

    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

    Dependendo do uso existente das const char*instâncias globais em seu projeto, esse comportamento pode exigir intervenção manual em vários locais.

lubgr
fonte
essa terminação diferente de zero é definitivamente uma pegadinha - também. Agora eu preciso passar pelos nossos SVs. Suponho que você faria std::string(sv).c_str()ao passar para a API?
darune 08/10/19
@ Darune Essa é uma opção, mas as suposições da API devem ser verificadas, certo ?! Se você vai com someLegacyFct(std::string(sv).c_str())e este backend de alguma forma armazena o ponteiro ...
lubgr
que é correcto - apenas com que a suposição vida
darune
A segunda questão é "felizmente" não será um grande problema para nós. Nossa estrutura de empresa possui sua própria classe de strings (eu sei ...), com um const char*construtor explícito . Portanto, a construção explícita de std::stringfrom string_viewseria consistente no nosso caso.
PixelSupreme 9/10/19