Препроцессор С++ # определение ключевого слова. Соответствует ли это стандартам?
Помогите решить дебаты, которые происходят в комментариях на на этот вопрос о bool и 1:
Может ли стандартизованный препроцессор С++ разрешить использовать #define
для переопределения ключевого слова языка? Если да, должен ли это соответствовать стандартизованному препроцессору С++?
Если программа на С++ переопределяет ключевое слово языка, может ли эта программа соответствовать стандартам?
Ответы
Ответ 1
В С++ самым близким к запрещению #define
ключевого слова является §17.4.3.1.1/2, что только запрещает его в блоке трансляции, который включает в себя стандартный заголовок библиотеки:
Единица перевода, которая включает заголовок, не должна содержать макросов, которые определяют имена, объявленные или определенные в этом заголовке. Также такая единица перевода не определяет макросы для имен, лексически идентичных ключевым словам.
Второе предложение этого абзаца было изменено в С++ 0x, чтобы прямо запретить #define
ключевое слово (С++ 0x FCD §17.6.3.3.1):
Единица перевода не должна содержать имена #define или #undef, лексически идентичные ключевым словам.С >
Изменить: Как отметил Кен Блум в комментариях к его ответу, правила не изменились в С++ 0x; текст только что был перестроен, чтобы запутать таких людей, как я.: -)
Ответ 2
Работает с 2005-10-19 рабочий проект С++ (так как у меня нет стандартной поддержки):
В разделе 16.3 грамматика для #define
должна быть #define identifier replacement-list-newline
(объектно-ориентированные макросы) или одна из нескольких конструкций, начинающихся с #define identifier lparen
(функционально-подобных макросов). identifier
определены в разделе 2.10 как identifier-nondigit | identifier identifier-nondigit | identifier digit
. В разделе 2.11 указывается, что определенный список идентификаторов безоговорочно рассматривается как ключевые слова в фазе 7 компиляции (раздел 2.1), и я заключаю, что поэтому они не обрабатываются специально на этапе 4, что является расширением препроцессора. Таким образом, кажется, что стандарт требует, чтобы препроцессор позволял вам переопределять языковые ключевые слова (перечисленные в разделе 2.11).
Однако препроцессор имеет собственное ключевое слово, а именно defined
, а также список предопределенных макросов (раздел 16.8). В разделе 16.8 указано, что поведение undefined, если вы переопределите их, но не запрещает препроцессору распознавать их как имена макросов.