Препроцессор С++ # определение ключевого слова. Соответствует ли это стандартам?

Помогите решить дебаты, которые происходят в комментариях на на этот вопрос о 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, если вы переопределите их, но не запрещает препроцессору распознавать их как имена макросов.