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
?
É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:
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.
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.
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.