Можно ли переопределить ключевое слово С++?

В этой статье от Гуру недели говорится: It is illegal to #define a reserved word. Это правда? Я не могу найти что-либо в норме, и я уже видел, как программисты переопределяют новые, например.

Ответ 1

17.4.3.1.1 Макро-имена [lib.macro.names]

1 Каждое имя, определенное как макрос в заголовке, зарезервировано для реализации для любого использования, если единица перевода включает заголовок .164)
2 Единица перевода, которая включает заголовок, не должна содержать макросов, которые определяют имена, объявленные или определенные в этом заголовке. И такая единица перевода не будет определять макросы для имен, лексически идентичных ключевым словам.

Кстати, new является оператором, и он может быть перегружен (заменен) пользователем, предоставив свою собственную версию.

Ответ 2

Соответствующий раздел из С++ 11:

17.6.4.3.1 Макро-имена [macro.names]

1 Блок перевода, который включает стандартный заголовок библиотеки, не должен объявлять имена #define или #undef в любом заголовке стандартной библиотеки.
2 Единица перевода не должна содержать имена #define или #undef, лексически идентичные ключевым словам.

Параграф 1 из С++ 03 удален. Второй параграф был разделен на две части. Первая половина теперь изменена, чтобы конкретно указать, что она применима только к стандартным заголовкам. Второй пункт был расширен, чтобы включать в себя любую единицу перевода, а не только те, которые включают заголовки.

Однако Обзор для этого раздела стандарта (17.6.4.1 [constraints.overview]) гласит:

В этом разделе описаны ограничения на программы на С++, которые используют средства стандартной библиотеки С++.

Поэтому, если вы не используете стандартную библиотеку С++, тогда вы можете делать то, что хотите.

Итак, чтобы ответить на ваш вопрос в контексте С++ 11: вы не можете определять (или не определять) имена, идентичные ключевым словам в любой единицы перевода, если вы используете стандартную библиотеку С++.

Ответ 3

Они на самом деле там неправы или, по крайней мере, не рассказывают об этом всю историю. Настоящая причина, по которой она запрещена, заключается в том, что она нарушает правило с одним определением (которое, кстати, также упоминается как вторая причина, по которой оно незаконно).

Чтобы убедиться, что это действительно разрешено (для переопределения ключевых слов), по крайней мере, если вы не используете стандартные библиотеки, вам нужно взглянуть на совершенно другую часть стандарта, а именно на фазы перевода. В нем говорится, что вход только разложен на токены препроцессора до того, как будет выполнена предварительная обработка, и посмотрев на те, которые не различаются между private и fubar, они оба identifiers для препроцессора. Позже, когда ввод разбивается на token, замена уже состоялась.

Было указано, что существует ограничение на программы, которые должны использовать стандартные библиотеки, но не очевидно, что пример переопределения private делает это (в отличие от "Person # 4: The Legal Lawyer" ) фрагмент, который использует его для вывода на cout).

В последнем примере он упомянул, что трюк не растоптан другими переводческими единицами или не преткновения на другом. Имея это в виду, вы должны, вероятно, учитывать возможность того, что стандартная библиотека используется где-то в другом месте, что поместит это ограничение в действие.

Ответ 4

Вот что вы можете сделать, если не хотите, чтобы кто-то использовал goto's. Просто отбросьте где-нибудь в своем коде, где он этого не заметит.

#define goto { int x = *(int *)0; } goto

Теперь каждый раз, когда он пытается использовать оператор goto, его программа выйдет из строя.

Ответ 5

Это не так, насколько я знаю, незаконно - никакой компилятор, с которым я столкнулся, покажет ошибку, если вы делаете

#define true false

#defining определенные ключевые слова, вероятно, будут генерировать ошибки в компиляции по другим причинам. Но многие из них просто приведут к очень странному поведению программы.