web-dev-qa-db-fra.com

en quoi std :: u8string sera différent de std :: string?

Si j'ai une chaîne:

std::string s = u8"你好";

et en C++ 20,

std::u8string s = u8"你好";

comment std::u8string sera différent de std::string?

11
user963241

Étant donné que la différence entre u8string Et string est que l'un est basé sur char8_t Et l'autre sur char, le la vraie question est quelle est la différence entre l'utilisation de chaînes basées sur char8_t et des chaînes basées sur char.

Cela se résume vraiment à ceci: l'encodage basé sur le type.

Toute chaîne basée sur char (char*, char[], string, etc.) peut être codée en UTF-8. Mais là encore, il se peut que ce ne soit pas le cas . Vous pouvez développer votre code en supposant que chaque équivalent char* Sera codé en UTF-8. Et vous pouvez écrire un u8 Devant chaque littéral de chaîne et/ou sinon vous assurer qu'ils sont correctement encodés. Mais:

  1. Le code d'autres personnes peut ne pas être d'accord. Vous ne pouvez donc pas utiliser de bibliothèque susceptible de renvoyer des char* Qui n'utilisent pas le codage UTF-8.

  2. Vous pourriez accidentellement violer vos propres préceptes. Après tout, char not_utf8[] = "你好"; Est pris en charge sous condition C++. L'encodage de ce char[] Sera l'encodage étroit du compilateur ... quel que soit qui est . Il peut s'agir d'UTF-8 sur certains compilateurs et de quelque chose d'autre sur d'autres.

  3. Vous ne pouvez pas dire au code des autres (ou même à d'autres personnes de votre équipe) que c'est ce que vous faites. Autrement dit, votre API ne peut pas déclarer qu'un char* Particulier est codé en UTF-8. Cela doit être quelque chose que l'utilisateur suppose ou a autrement lu dans votre documentation, plutôt que quelque chose qu'ils voient dans le code.

Notez qu'aucun de ces problèmes n'existe pour les utilisateurs de UTF-16 ou UTF-32. Si vous utilisez une chaîne basée sur char16_t, Tous ces problèmes disparaissent. Si le code d'autres personnes renvoie une chaîne char16_t, Vous savez ce qu'ils font. S'ils retournent autre chose, alors vous savez que ces choses ne sont probablement pas UTF-16. Votre code basé sur UTF-16 peut interagir avec le leur. Si vous écrivez une API qui renvoie une chaîne basée sur char16_t, Tous ceux qui utilisent votre code peuvent voir à partir du type de la chaîne quel est son codage. Et cela est garanti comme une erreur de compilation: `char16_t not_utf16 [] =" 你好 ";

Maintenant oui, il n'y a aucune garantie de ces choses. Toute chaîne char16_t Particulière peut contenir n'importe quelle valeur, même celles qui sont illégales pour UTF-16. Mais char16_t Représente un type pour lequel l'hypothèse par défaut est un encodage spécifique. Étant donné que si vous présentez une chaîne de ce type qui n'est pas encodée en UTF-16, il ne serait pas déraisonnable de considérer cela comme une erreur/perfidie par l'utilisateur, qu'il s'agit d'une violation de contrat.

Nous pouvons voir comment C++ a été impacté par le manque d'installations similaires basées sur le type pour UTF-8. Considérez filesystem::path. Il peut prendre des chaînes dans n'importe quel encodage Unicode. Pour UTF-16/32, le constructeur de path prend des chaînes basées sur char16/32_t. Mais vous ne pouvez pas passer une chaîne UTF-8 au constructeur de path; le constructeur basé sur char suppose que le codage est le codage étroit défini par l'implémentation, et non UTF-8. Donc, à la place, vous devez utiliser filesystem::u8path, Qui est une fonction distincte qui renvoie un path, construit à partir d'un Chaîne codée en UTF-8.

Ce qui est pire, c'est que si vous essayez de passer une chaîne basée sur char encodée en UTF-8 au constructeur de path ... ça compile très bien. Bien qu'il soit au mieux non portable, il peut sembler fonctionner.

char8_t, Et tous ses accessoires comme u8string, Existent pour permettre aux utilisateurs UTF-8 la même puissance que les autres encodages UTF. En C++ 20, filesystem::path Obtiendra des surcharges pour les chaînes basées sur char8_t, Et u8path Deviendra obsolète.

Et, en prime, char8_t N'a pas de langage d'alias spécial autour. Donc, une API qui prend des chaînes basées sur char8_t Est certainement une API qui prend un tableau de caractères, plutôt qu'un tableau d'octets arbitraire.

8
Nicol Bolas