Что такое использование универсальных имен символов в идентификаторах в C ++


11

C ++ стандарта (я заметил это в новом, но он уже существует в C ++ 03) определяет универсальные имена символов, написанные , как \uNNNNи \UNNNNNNNNи представляющие символы с Юникодом кодовыми NNNN/ NNNNNNNN. Это полезно для строковых литералов, тем более что явно определены строковые литералы UTF-8, UTF-16 и UCS-4. Однако универсальные символьные литералы также допускаются в идентификаторах. Какова мотивация этого?

Синтаксис, очевидно, полностью нечитабелен, идентификаторы могут быть искажены для компоновщика, и не существует какой-либо стандартной функции для извлечения символов по имени в любом случае. Так зачем кому-то использовать идентификатор с универсальными символьными литералами в нем?

Изменить: Поскольку он уже существовал в C ++ 03, дополнительный вопрос будет ли вы на самом деле видел код, который его использовал?

Ответы:


6

ОБНОВЛЕНИЕ - этот ответ, хотя он, казалось, имел смысл для меня и других, оказывается в значительной степени неправильным (и достаточно неправильным в отношении намерения, поскольку фактически является просто неправильным). Поскольку (как указано в комментарии AProgrammer) не разрешается использовать UCS вне строковых констант, когда один и тот же символ обычно может быть представлен в базовом наборе символов. Так что не используйте его для экранирования ключевых слов, как в моем примере; и не использовать его, чтобы сделать «идентификаторы», как 23skiddo, избегая2, Я думаю, что он все еще может быть использован для того, чтобы сделать имена совместимыми с внешними языками, но, похоже, только тогда, когда эти имена начинаются с буквы или расширенного символа и содержат только буквы, цифры, подчеркивание и расширенные символы - что кажется слишком ограничительным, чтобы должным образом поддержать это намерение. Поэтому должно быть так, что основной целью является (как в ответе AProgrammer) разрешить эти дополнительные символы в идентификаторах и разрешить редакторы исходного кода, где эти символы отображаются графически, при этом оставляя исходный файл в простом ASCII.


Программы на C ++ могут вызывать функции, написанные на других языках. Хорошая стратегия со стороны комитета по стандартизации состоит в том, чтобы обеспечить совместимость C ++ с другими языками, которые могут разрешать использование не алфавитно-цифровых символов или символов Юникода в именах функций, даже если такие языки еще не существуют. Стандарту не нужно указывать, как это будет работать на уровне компоновщика и т. Д .; но хорошо бы иметь определенный механизм, позволяющий это сделать.

Вам не нужно смотреть в будущее, чтобы увидеть использование этого. Предположим, у меня есть старая библиотека C с функцией в ней, называемой catch(или защищенной, или изменяемой) ... и я хочу вызвать ее из C ++. И по какой-то причине я не могу или не хочу изменять код C (Кстати, мне уже не раз приходилось иметь дело со старым кодом C, который использовал имя функции, которое стало ключевым словом C ++ ...)

С именами UC я могу написать это в заголовке, а затем просто вызвать 'catch_func ()':

extern "C" {
       int catc\u0068( int a, int b );  // C 'catch()' function
}
inline int catch_func( int a, int b ) { return catc\u0068(a,b); }

Конечно, это некрасиво, но это не имеет значения, так как это только в одном месте в заголовке. Тот же подход можно использовать для создания заглушек для вызова функций на других языках, и он работает, даже если имена являются ключевыми словами C ++ или Unicode, или в них есть пробелы .или другие знаки препинания.

Различные другие языки имеют устройства, позволяющие создавать идентификаторы, которые не следуют общему шаблону; например, в Verilog, \abcdявляется идентификатором, эквивалентным abcd, но \whileи \23skidooи также \44.e2являются идентификаторами, которые должны видеть префикс обратной косой черты как таковой. Из-за способа, которым используется Verilog, важно разрешить любые имена вообще, где они относятся к внешним интерфейсам.


Интересный вариант использования. Хотя я подозреваю (когда это возможно), было бы лучше написать небольшой C-файл для перевода имени (и, таким образом, можно использовать идентификатор C ++) и заставить C ++ вызывать эту C-функцию.
Томас Эдинг

1
Вы не можете написать это по двум причинам: во-первых, внешняя строка UCS и символьные литералы не могут ссылаться на символ в базовых наборах, не делая программу плохо информированной, во-вторых, если этого предложения не было, UCS обрабатываются на этапе 1 перевода и таким образом, не будет разницы в обработке между UCS, ссылающейся на символ в базовом наборе, и самим символом.
AProgrammer

4

Это позволяет системе, позволяющей символам юникода в идентификаторе, экспортировать исходный код в формате, компилируемом на любых стандартных соответствующих компиляторах. То есть, это способ кодировать юникод по основному набору символов (более или менее как кавычка-печать используется для электронной почты, системы, которые знают лучше, могут выполнять свою работу лучше, другие системы все еще работают).


2

Кто-то может захотеть создать идентификатор, используя символ иностранного языка, который нельзя ввести на клавиатуре или устройстве ввода. В качестве альтернативы, идентификатор может содержать символ, который нельзя распечатать, используя шрифт или возможности вывода устройства, но IDE хочет показать точное представление.


4
В первом случае идентификатор не будет выглядеть так, как будто он имеет этот символ, поэтому код будет нечитаемым, и идентификатор на самом деле не имеет значения для машины. И, во-вторых, представление в IDE - это совершенно отдельная проблема.
Ян Худек

1

C ++ требует, чтобы фактические расширенные символы, появляющиеся буквально в источнике, вели себя идентично универсальным именам символов. Разрешение универсальных имен символов в идентификаторах позволяет программистам использовать расширенные символы в идентификаторах.


Это фактические расширенные символы поддерживаются, они должны вести себя как соответствующие универсальные символы. Но они не должны быть поддержаны.
Ян Худек

1
Это правда, но в некотором смысле это упускает из виду то, что если комитет хочет указать, что реализации, поддерживающие расширенные символы, должны поддерживать использование этих символов в идентификаторах, то для этого необходимо, чтобы в идентификаторах были разрешены UCN. Т.е. UCN допускаются в идентификаторах не обязательно, потому что это так легко читается, и всем нравится вручную кодировать имена в шестнадцатеричном формате, а потому, что если спецификация хочет разрешить использование расширенных символов в идентификаторах, она делает это, указывая, что UCN разрешены в идентификаторах.
bames53
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.