Y a-t-il des pièges remplaçant le const const char [] par constexpr string_view?

17

Notre équipe travaille avec une base de code C ++ de 10 ans et plus et est récemment passée à un compilateur C ++ 17. Nous recherchons donc des moyens de moderniser notre code. Lors d'une conférence sur YouTube, j'ai entendu la suggestion de remplacer const char*les chaînes mondiales par constexpr string_view.

Étant donné que nous avons un certain nombre de ces const char*constantes de chaîne globales dans notre code, je veux demander s'il y a des problèmes ou des problèmes potentiels dont nous devons être conscients?

PixelSupreme
la source

Réponses:

15

Ces problèmes méritent d'être pris en compte:

  1. std::string_viewn'a pas besoin d'être nullterminé. Donc, si vous en remplacez certains const char*par string_viewet remplacez la construction d'une sous-chaîne déjà nullterminée char*par un string_viewvia std::string_view::substr, vous ne pouvez pas passer le pointeur sous-jacent à une API qui attend une nullchaîne terminée. Exemple (sans UB, mais qui est également facilement constructible):

    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. Bien que vous puissiez implicitement construire un à std::stringpartir d'un const char*, vous ne pouvez pas le faire avec un std::string_view. L'idée est qu'une copie complète ne devrait pas se produire sous la couverture, mais uniquement lorsqu'elle est explicitement demandée. Exemple:

    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

    Selon l'utilisation existante des const char*instances globales dans votre projet, ce comportement peut nécessiter une intervention manuelle à différents endroits.

lubgr
la source
que la terminaison non nulle est définitivement un piège. Maintenant, je dois passer par nos SV. Je suppose que vous feriez std::string(sv).c_str()plutôt pour passer à l'API?
darune
@darune C'est une option, mais alors les hypothèses de durée de vie de l'API devraient être vérifiées, non?! Si vous y allez someLegacyFct(std::string(sv).c_str())et que ce backend stocke en quelque sorte le pointeur ...
lubgr
c'est exact - seulement avec cette hypothèse de vie
darune
Le deuxième problème est «heureusement» ne va pas être un gros problème pour nous. Notre framework d'entreprise a sa propre classe de chaîne (je sais ...), avec un const char*constructeur explicite . Donc, la construction explicite de std::stringfrom string_viewserait juste cohérente dans notre cas.
PixelSupreme