Препроцессор C ++ # определяет ключевое слово. Соответствует ли оно стандартам? - PullRequest
19 голосов
/ 28 апреля 2010

Помогите разрешить спор, который продолжается в комментариях на этот вопрос о bool и 1 :

Может ли стандартизированный препроцессор C ++ позволить использовать #define для переопределения ключевого слова языка? Если это так, должен ли это разрешать стандартизированный препроцессор C ++?

Если программа на C ++ переопределяет ключевое слово языка, может ли эта программа соответствовать стандартам?

Ответы [ 3 ]

22 голосов
/ 28 апреля 2010

В C ++ самым близким к запрету #define ключевому слову является §17.4.3.1.1 / 2, который запрещает его только в единице перевода, которая включает стандартный заголовок библиотеки:

Единица перевода, которая включает заголовок, не должна содержать макросов, которые определяют имена, объявленные или определенные в этом заголовке. Также такая единица перевода не должна определять макросы для имен, лексически идентичных ключевым словам.

Второе предложение этого абзаца было изменено в C ++ 0x на прямой запрет #define с использованием ключевого слова (C ++ 0x FCD §17.6.3.3.1):

Модуль перевода не должен содержать имена #define или #undef, лексически идентичные ключевым словам.

Редактировать: Как указал Кен Блум в комментариях к своему ответу , правила в C ++ 0x не изменились; текст был только что переставлен, чтобы сбить с толку таких людей, как я. : -)

5 голосов
/ 28 апреля 2010

Работа с 2005-10-19 C ++ рабочий проект (так как у меня нет стандартного подручного):

В разделе 16.3 грамматика для #define определяется как #define identifier replacement-list-newline (объектные макросы) или одна из нескольких конструкций, начинающихся с #define identifier lparen (функциональные макросы). identifier s определены в разделе 2.10 как identifier-nondigit | identifier identifier-nondigit | identifier digit. В разделе 2.11 указано, что определенный список идентификаторов безусловно рассматривается как ключевые слова на этапе 7 компиляции (раздел 2.1), и я заключаю, что поэтому они не обрабатываются специально на этапе 4, который является расширением препроцессора. Таким образом, похоже, что стандарт требует, чтобы препроцессор позволил вам переопределить ключевые слова языка (перечисленные в разделе 2.11) .

Однако препроцессор имеет собственное ключевое слово, а именно defined, а также список предопределенных макросов (раздел 16.8). Раздел 16.8 утверждает, что поведение не определено, если вы переопределите их, но не запрещает препроцессору распознавать их как имена макросов.

1 голос
/ 06 сентября 2018

Это не разрешено, согласно C ++ 11 [macro.names]:

Единица перевода не должна #define или #undef имен, лексически идентичных ключевым словам, идентификаторам, перечисленным в таблице 3, или токенам атрибутов, описанным в 7.6.

«Идентификаторы, перечисленные в таблице 3»: final и override; а токены-атрибуты - это идентификаторы в [[fallthrough]] и т. д.

Этот пункт также соответствует последнему стандарту.

...