Препроцессор C++ # определяет ключевое слово. Соответствует ли оно стандартам?
Помогите решить спор, который происходит в комментариях к этому вопросу о bool и 1:
Может ли стандартизированный препроцессор C++ позволять использовать #define
переопределить ключевое слово языка? Если это так, должен ли это соответствовать стандартному препроцессору C++?
Если программа на C++ переопределяет ключевое слово языка, может ли эта программа соответствовать стандартам?
3 ответа
В C++ ближе всего к запрету #define
ключевое слово ing - §17.4.3.1.1/2, которое запрещает его только в модуле перевода, который включает стандартный заголовок библиотеки:
Модуль перевода, который включает заголовок, не должен содержать макросов, которые определяют имена, объявленные или определенные в этом заголовке. Такой блок перевода также не должен определять макросы для имен, лексически идентичных ключевым словам.
Второе предложение этого абзаца было изменено в C++0x на прямой запрет #define
Использование ключевого слова (C++0x FCD §17.6.3.3.1):
Модуль перевода не должен использовать имена #define или #undef, лексически идентичные ключевым словам.
Изменить: Как отметил Кен Блум в комментариях к своему ответу, правила не изменились в C++0x; текст был только что переработан, чтобы сбить с толку таких людей, как я.:-)
Это не разрешено, согласно C++11 [macro.names]:
Переводчик не должен
#define
или же#undef
имена, лексически идентичные ключевым словам, идентификаторам, перечисленным в таблице 3, или атрибутам-токенам, описанным в 7.6.
"Идентификаторы, перечисленные в таблице 3" final
а также override
; и атрибуты-токены являются идентификаторами в [[fallthrough]]
и так далее.
Этот пункт все еще в последней версии тоже.
Работа с рабочего проекта C++ 2005-10-19 (так как у меня нет стандартного подручного):
Раздел 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 утверждает, что поведение не определено, если вы переопределите их, но не запрещает препроцессору распознавать их как имена макросов.