modules - gcc c++ 20




C++ 20 'char8_t' é o mesmo que nosso antigo 'char'? (2)

Isenção de responsabilidade: sou o autor das propostas char8_t P0482 e P1423 .

No C ++ 20, char8_t é um tipo distinto de todos os outros tipos. Na proposta relacionada para C, N2231 (que precisa de uma atualização e nova proposta para o WG14), char8_t seria um typedef de unsigned char semelhante aos typedefs existentes para char16_t e char32_t .

No C ++ 20, char8_t tem uma representação subjacente que corresponde ao unsigned char . Portanto, ele tem o mesmo tamanho (pelo menos 8 bits, mas pode ser maior), alinhamento e classificação de conversão de número inteiro como unsigned char , mas possui regras de alias diferentes.

Em particular, char8_t não foi adicionado à lista de tipos no [basic.lval]p11 . [basic.life]p6.4 , [basic.types]p2 ou [basic.types]p4 . Isso significa que, diferentemente do unsigned char , ele não pode ser usado para o armazenamento subjacente de objetos de outro tipo, nem para examinar a representação subjacente de objetos de outros tipos; em outras palavras, ele não pode ser usado para alias outros tipos. Uma conseqüência disso é que objetos do tipo char8_t podem ser acessados ​​via ponteiros para char ou unsigned char , mas ponteiros para char8_t não podem ser usados ​​para acessar char ou dados de unsigned char . Em outras palavras:

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

A motivação para um tipo distinto com essas propriedades é:

  1. Fornecer um tipo distinto para dados de caracteres UTF-8 x dados de caracteres com uma codificação dependente da localidade ou que exija especificação separada.

  2. Para habilitar a sobrecarga para literais de cadeia comuns versus literais de cadeia UTF-8 (pois eles podem ter codificações diferentes).

  3. Para garantir um tipo não assinado para dados UTF-8 (se char é assinado ou não é definido com implementação).

  4. Para permitir melhor desempenho por meio de um tipo sem serrilhado; os otimizadores podem otimizar melhor tipos que não alias outros tipos.

Na documentation referência do CPP,

Notei por char

Os tipos de caracteres são grandes o suficiente para representar qualquer unidade de código UTF-8 de oito bits (desde C ++ 14)

e para char8_t

tipo para representação de caracteres UTF-8, necessário para ser grande o suficiente para representar qualquer unidade de código UTF-8 (8 bits)

Isso significa que ambos são do mesmo tipo? Ou char8_t tem algum outro recurso?


char8_t não é o mesmo que char . Ele se comporta exatamente da mesma forma que o unsigned char embora por [basic.fundamental]/9

Tipo char8_t indica um tipo distinto cujo tipo subjacente é um unsigned char . Os tipos char16_t e char32_t denotam tipos distintos cujos tipos subjacentes são uint_least16_t e uint_least32_t , respectivamente, em <cstdint>.

ênfase minha

Observe que, como o padrão o chama de tipo distinto , código como

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

imprimirá 0 (falso), mesmo que char8_t seja implementado como um unsigned char . Isso ocorre porque não é um alias, mas um tipo distinto.

Outro aspecto a ser observado é que o char pode ser implementado como signed char ou unsigned char . Isso significa que é possível que char tenha o mesmo intervalo e representação que char8_t , mas eles ainda são tipos separados. char , char signed char , signed char unsigned char e char8_t têm o mesmo tamanho, mas são todos tipos distintos.





c++20