web-dev-qa-db-fra.com

C ++ 20 'char8_t' est-il le même que notre ancien 'char'?

Dans la référence CPP documentation ,

J'ai remarqué pour char

Les types de caractères sont suffisamment grands pour représenter n'importe quelle unité de code huit bits UTF-8 (depuis C++ 14)

et pour char8_t

type pour la représentation des caractères UTF-8, doit être suffisamment grand pour représenter n'importe quelle unité de code UTF-8 (8 bits)

Est-ce à dire que les deux sont du même type? Ou est-ce que char8_t avez une autre fonctionnalité?

35
Pavan Chandaka

char8_t n'est pas identique à char. Il se comporte exactement comme unsigned char bien que par [basic.fundamental]/9

Tapez char8_­t désigne un type distinct dont le type sous-jacent est unsigned char. Les types char16_­t et char32_­t désigne des types distincts dont les types sous-jacents sont uint_­least16_­t et uint_­least32_­t, respectivement, dans <cstdint>.

mettre l'accent


Notez que puisque la norme l'appelle un type distinct, un code comme

std::cout << std::is_same_v<unsigned char, char8_t>;

imprimera 0 (faux), même si char8_t est implémenté en tant que unsigned char. C'est parce que ce n'est pas un alias, mais un type distinct.


Une autre chose à noter est que char peut être implémenté en tant que signed char ou unsigned char. Cela signifie qu'il est possible que char ait la même plage et la même représentation que char8_t, mais ce sont toujours des types distincts. char, signed char, unsigned char, et char8_t ont la même taille, mais ce sont tous des types distincts.

41
NathanOliver

Avertissement: je suis l'auteur du char8_tP0482 et P142 propositions.

En C++ 20, char8_t est un type distinct de tous les autres types. Dans la proposition connexe pour C, N2231 (qui a besoin d'une mise à jour et d'une nouvelle proposition au WG14), char8_t serait un typedef de unsigned char similaire aux typedefs existants pour char16_t et char32_t.

En C++ 20, char8_t a une représentation sous-jacente qui correspond à unsigned char. Il a donc la même taille (au moins 8 bits, mais peut être plus grande), l'alignement et le rang de conversion entier que unsigned char, mais avec des règles d'alias différentes.

En particulier, char8_t n'a pas été ajouté à la liste des types à [basic.lval] p11 . [basic.life] p6.4 , [basic.types] p2 , ou [basic.types] p4 . Cela signifie que, contrairement à unsigned char, il ne peut pas être utilisé pour le stockage sous-jacent d'objets d'un autre type, ni pour examiner la représentation sous-jacente d'objets d'autres types; en d'autres termes, il ne peut pas être utilisé pour alias d'autres types. Une conséquence de cela est que les objets de type char8_t est accessible via des pointeurs vers char ou unsigned char, mais pointe vers char8_t ne peut pas être utilisé pour accéder à char ou unsigned char Les données. En d'autres termes:

reinterpret_cast<const char   *>(u8"text"); // Ok.
reinterpret_cast<const char8_t*>("text");   // Undefined behavior.

La motivation pour un type distinct avec ces propriétés est:

  1. Pour fournir un type distinct pour les données de caractères UTF-8 par rapport aux données de caractères avec un codage dépendant des paramètres régionaux ou nécessitant des spécifications distinctes.

  2. Pour activer la surcharge pour les littéraux de chaîne ordinaires par rapport aux littéraux de chaîne UTF-8 (car ils peuvent avoir des encodages différents).

  3. Pour garantir un type non signé pour les données UTF-8 (que char soit signé ou non signé est défini par l'implémentation).

  4. Pour permettre de meilleures performances via un type sans alias; les optimiseurs peuvent mieux optimiser les types qui ne sont pas des alias d'autres types.

22
Tom Honermann