Препроцессор 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 (функциональные макросы). identifiers определены в разделе 2.10, чтобы быть identifier-nondigit | identifier identifier-nondigit | identifier digit, В разделе 2.11 указано, что определенный список идентификаторов безоговорочно обрабатывается как ключевые слова на этапе 7 компиляции (раздел 2.1), и я прихожу к выводу, что поэтому они не обрабатываются специально на этапе 4, который является расширением препроцессора. Таким образом, похоже, что стандарт требует, чтобы препроцессор позволил вам переопределить ключевые слова языка (перечисленные в разделе 2.11).

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

Другие вопросы по тегам