web-dev-qa-db-fra.com

Comment convertir un std :: string_view en un const char *?

Compiler avec gcc-7.1 avec le drapeau -std=c++17, le programme suivant génère une erreur:

#include <string_view>
void foo(const char* cstr) {}
void bar(std::string_view str){
    foo(str);
}

Le message d'erreur est

In function 'void bar(std::string_view)':
error: cannot convert 'std::string_view {aka std::basic_string_view<char>}' to 'const char*' for argument '1' to 'void foo(const char*)'
 foo(str);

Je suis surpris qu'il n'y ait pas de conversion en const char* parce que d'autres bibliothèques (abseil, bde), fournissent des string_view classes qui se convertissent implicitement en const char*.

19
Justin Raymond

Un std::string_view Ne fournit pas de conversion en un const char* Car il ne stocke pas de chaîne terminée par null . Il stocke un pointeur sur le premier élément et la longueur de la chaîne, en gros. Cela signifie que vous ne pouvez pas le passer à une fonction qui attend une chaîne terminée par un caractère nul, comme foo (comment allez-vous obtenir la taille?) Qui attend un const char*, Et il en était ainsi a décidé que cela n'en valait pas la peine.

Si vous savez avec certitude que vous disposez d'une chaîne terminée par un caractère nul, vous pouvez utiliser std::string_view::data .

Si vous ne l'êtes pas, vous devriez reconsidérer si l'utilisation d'un std::string_view En premier lieu est une bonne idée, car si vous voulez une chaîne terminée par null garantie std::string Est ce que vous voulez. Pour une ligne unique, vous pouvez utiliser std::string(object).data().

26
Rakete1111

Faites simplement une std::string(string_view_object).c_str() pour obtenir une copie temporaire garantie terminée par un caractère nul (et nettoyez-la à la fin de la ligne).

Ceci est nécessaire car la vue chaîne ne garantit pas la terminaison nulle. Vous pouvez avoir une vue au milieu d'un tampon plus long, par exemple.

Si ce cas d'utilisation est coûteux et que vous avez prouvé qu'il s'agit d'un contrôle de bouteille, vous pouvez écrire un string_view Augmenté qui suit s'il est terminé par null (en gros, s'il a été construit à partir d'un char const* Brut ).

Ensuite, vous pouvez écrire un type d'aide qui prend ce string_view Augmenté et le copie dans un std::string Ou stocke directement le string_view Augmenté, et a un cast implicite vers- char const* Qui renvoie le tampon correctement terminé par null.

Ensuite, utilisez ce type d'aide augmenté partout dans votre base de code au lieu de string_view, Augmentant éventuellement l'interaction de la vue de chaîne avec la chaîne std également pour détecter les cas où vous avez une vue qui va à la fin du tampon de chaîne std.

Mais vraiment, c'est probablement exagéré.

Une meilleure approche consiste probablement à réécrire les API qui prennent const char* Pour prendre string_view.

23

Vous pouvez appeler foo(std::string(str).c_str()).

5
Maxime Guinin