Codificação Unicode para literais de string em C ++ 11

Após uma questão relacionada , gostaria de perguntar sobre o novo caractere e tipos literais de string no C ++ 11. Parece que agora temos quatro tipos de caracteres e cinco tipos de literais de string. Os tipos de caracteres:

char a = '\x30'; // character, no semantics wchar_t b = L'\xFFEF'; // wide character, no semantics char16_t c = u'\u00F6'; // 16-bit, assumed UTF16? char32_t d = U'\U0010FFFF'; // 32-bit, assumed UCS-4 

E os literais de string:

 char A[] = "Hello\x0A"; // byte string, "narrow encoding" wchar_t B[] = L"Hell\xF6\x0A"; // wide string, impl-def'd encoding char16_t C[] = u"Hell\u00F6"; // (1) char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2) auto E[] = u8"\u00F6\U0010FFFF"; // (3) 

A questão é a seguinte: As referências de caracteres \x / \u / \U livremente combináveis ​​com todos os tipos de string? Todos os tipos de string são de largura fixa, isto é, os arrays contêm exatamente tantos elementos quanto aparecem no literal, ou as referências \x / \u / \U são expandidas em um número variável de bytes? As cadeias u"" e u8"" possuem semântica de codificação, por exemplo, eu posso dizer char16_t x[] = u"\U0010FFFF" , e o ponto de código não-BMP é codificado em uma seqüência UTF16 de duas unidades? E da mesma forma para u8 ? Em (1), posso escrever substitutos solitários com \u ? Finalmente, alguma das funções de string é codificadora de reconhecimento (isto é, elas são caracterizadas e podem detectar seqüências de bytes inválidos)?

Esta é uma questão aberta, mas gostaria de obter uma imagem o mais completa possível dos novos resources de codificação UTF e de tipo do novo C ++ 11.

As referências de caracteres \ x / \ u / \ U são livremente combináveis ​​com todos os tipos de string?

Não. \x pode ser usado em qualquer coisa, mas \u \U só podem ser usados ​​em strings que são especificamente codificadas em UTF. No entanto, para qualquer string codificada em UTF, \u \U pode ser usado como você achar adequado.

Todos os tipos de string são de largura fixa, isto é, os arrays contêm exatamente tantos elementos quanto aparecem no literal, ou as referências \ x / \ u / \ U são expandidas em um número variável de bytes?

Não do jeito que você quer dizer. \x , \u e \U são convertidos com base na codificação da cadeia de caracteres. O número desses valores de “unidades de código” (usando termos Unicode. Um char16_t é uma unidade de código UTF-16) depende da codificação da string de contenção. O literal u8"\u1024" criaria uma string contendo 2 char s mais um terminador nulo. O literal u"\u1024" criaria uma string contendo 1 char16_t mais um terminador nulo.

O número de unidades de código usadas é baseado na codificação Unicode.

As cadeias u “” e u8 “” possuem semântica de codificação, por exemplo, eu posso dizer char16_t x [] = u “\ U0010FFFF”, e o ponto de código não-BMP é codificado em uma seqüência UTF16 de duas unidades?

u"" cria uma string codificada em UTF-16. u8"" cria uma string codificada em UTF-8. Eles serão codificados pela especificação Unicode.

Em (1), posso escrever substitutos solitários com \ u?

Absolutamente não. A especificação proíbe expressamente o uso dos pares substitutos UTF-16 (0xD800-0xDFFF) como pontos de código para \u ou \U

Finalmente, alguma das funções de string é codificadora de reconhecimento (isto é, elas são caracterizadas e podem detectar seqüências de bytes inválidos)?

Absolutamente não. Bem, permita-me reformular isso.

std::basic_string não lida com codificações Unicode. Eles certamente podem armazenar strings codificadas em UTF. Mas eles só podem pensar nelas como sequências de char , char16_t ou char32_t ; eles não podem pensar neles como uma seqüência de pontos de código Unicode que são codificados com um mecanismo específico. basic_string::length() retornará o número de unidades de código, não pontos de código. E obviamente, as funções de string de biblioteca padrão C são totalmente inúteis

Deve-se notar, entretanto, que “length” para uma string Unicode não significa o número de pontos de código. Alguns pontos de código estão combinando “caracteres” (um nome infeliz), que combinam com o ponto de código anterior. Portanto, vários pontos de código podem mapear para um único caractere visual.

O iostreams pode, de fato, ler / gravar valores codificados em Unicode. Para fazer isso, você terá que usar uma localidade para especificar a codificação e inseri-la corretamente nos vários locais. É mais fácil dizer do que fazer, e não tenho código para mostrar como.