Как правильно объявить char8_t для диакритических букв? - PullRequest
0 голосов
/ 26 января 2020

Я пытаюсь инициализировать некоторые диакритические латинские буквы , используя новый тип char8_t:

constexpr char8_t french_letter_A_1 = 'À';//does not function properly

Однако Visual Studio 2019 предлагает мне следующий «символ, представленный универсальное символьное имя «\ u (имя)» не может быть представлено в текущей кодовой странице », и символ не может быть отображен должным образом; Если я пытаюсь явно объявить символ как u8, например:

constexpr char8_t french_letter_A_2 = u8'Â';//has error

Он даже выдаст ошибку "буквенное значение символа UTF-8 не может занимать более одной единицы кода" ; но недиакритические буквы можно успешно интерпретировать как буквы UTF-8:

constexpr char8_t french_letter_A_0 = u8'A';//but ASCII letters are fine

Мне интересно, как правильно объявить символ UTF-8 с помощью Visual C ++ ... или я неправильно понимаю концепцию char8_t, и лучше вместо этого использовать что-то еще?

Редактировать: я понял, что char8_t не поддерживает эти символы не ASCII. Какой тип символа я должен использовать вместо этого?

Ответы [ 2 ]

1 голос
/ 31 января 2020

char8_t, как char, signed char и unsigned char, имеет размер 1 байт. На большинстве платформ (но не на всех!) Это означает, что это 8-битный тип, способный содержать только 256 дискретных значений. Unicode 12.1 определяет 137 994 символа. Очевидно, что все они не могут вписаться в одно char8_t значение!

Типы "символов" C и C ++, к сожалению, плохо названы. Если бы мы разрабатывали новый язык с современной терминологией, мы бы назвали их некоторыми вариациями code_unit, поскольку они лучше отражают то, как они фактически используются. char32_t является единственным типом символов, который в настоящее время гарантированно может содержать значение кодовой точки для каждого символа в соответствующем наборе символов (стандарты C и C ++ утверждают, что wchar_t тоже может, но это противоречит существующей практике ).

Глядя на ваш пример, À - это U + 00C0 {ПИСЬМО ЛАТИНСКОГО КАПИТА A С МОЛОДОЙ} (или на самом деле это U + 0041 {ПИСЬМО ЛАТИНСКОГО КАПИТАЛА A}, за которым следует ̀ U + 0300 {КОМБИНИРОВАННАЯ МОЩНОСТЬ ACCENT}? Юникод так сложен). Кодировка UTF-8 U + 00C0 составляет 0xC3 0x80. Какое значение должно содержать french_letter_A_1? Он не может содержать оба значения кодовых единиц. И если значение должно быть кодовой точкой, то мы либо в ситуации, когда (переносимо) может поддерживаться только 256 символов, либо, что еще хуже, иногда значения char8_t являются кодовыми точками, а иногда - кодовыми единицами.

Реальность такова, что литералы символов C и C ++ ограничены всего несколькими символами, чем в исходном наборе символов basi c . Этого достаточно, если вы пишете только на Engli sh -приложении. Но для современных приложений литералы символов имеют ограниченное использование.

Как уже говорил Николь, работа с большинством символов вне исходного набора символов c требует реальной обработки текста в строках. К сожалению, стандарты C и C ++ здесь не сильно помогают. Это то, что SG16 работает над улучшением.

0 голосов
/ 26 января 2020

UTF-8 - это кодировка для кодовых точек Unicode. В UTF-8 кодовая точка разбивается на один или несколько «октетов» (8-битовых слов), называемых единицами кода UTF-8. Тип C ++ 20, представляющий кодовую единицу UTF-8: char8_t.

Один char8_t - это только одна кодовая единица UTF-8. Следовательно, он может представлять только кодовую точку Unicode, кодировка UTF-8 которой занимает всего 1 единицу кода. Visual Studio сообщает, что «символ», который вы пытаетесь сохранить в char8_t, требует более 1 единицы кода и, следовательно, не может быть сохранен в таком типе. Единственными кодовыми точками Unicode, которые UTF-8 кодирует в одной кодовой единице, являются кодовые точки ASCII.

При работе с UTF-8 (или любой кодировкой Unicode, которая не является UTF-32 в этом отношении), вы не имеете дело с «персонажами»; Вы имеете дело с строками : смежными последовательностями единиц кода. Каждый раз, когда вы хотите иметь дело с UTF-8, вы должны использовать какой-то тип строки char8_t.

...