неопределить и переопределить макрос __cplusplus

Я хочу отменить и переопределить макрос __cplusplus, однако, ошибка компиляции:__cplusplus was not declared in this scope

#define TEMP_VERSION __cplusplus // temporary macro to hold the __cplusplus  containt
#undef __cplusplus
#define __cplusplus TEMP_VERSION  // redefine __cplusplus

#define AA 111
#undef AA
#define AA 111

int main()
{
cout << "__cplusplus = "<<__cplusplus<<endl; // It doesn't work
cout << "AA = "<<AA<<endl; // It works

return 0;
}
  • Вопрос 1: Почему он не работает с __cplusplus но работает с AA

Я знаю, что это действительно ужасно, но причина, по которой я не определяю макрос, заключается в том, что я использую стороннее ПО, где они не используют #ifdef __cplusplusЯ имею в виду содержание #ifdef __cplusplus ... #endif неправильно. Поэтому вместо того, чтобы менять их программное обеспечение, я решил сделать следующее

#define TEMP_VERSION __cplusplus
#undef __cplusplus
#include <third_party_sw.h>
#define __cplusplus TEMP_VERSION
  • Вопрос 2: Как вы думаете, это хороший подход?

1

Решение

Вопрос 1: Почему он не работает с __cplusplus, но работает с AA

Так как __cplusplus является предопределенным макросом, и поведение (не) его определения не определено:

стандартный черновик [cpp.predefined]

Если какое-либо из предварительно определенных имен макросов в этом подпункте или определенный идентификатор являются предметом директивы предварительной обработки #define или #undef, поведение не определено. …

AA не является предопределенным макросом, и идентификатор не зарезервирован. Можно (пере) определить его.


Вопрос 2: Как вы думаете, это хороший подход?

(Пере) определение зарезервированных идентификаторов никогда не является хорошим подходом. Даже переопределение пользовательских макросов является сомнительным предложением.

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

1

Другие решения

Из стандарта C ++ ([cpp.predefined, 3-4]):

Значения предопределенных макросов (кроме __FILE__ а также __LINE__)
оставаться неизменным на протяжении всего перевода. Если какой-либо из
предварительно определенные имена макросов в этом подпункте или определенный идентификатор,
является предметом директивы предварительной обработки #define или #undef,
поведение не определено.

Другими словами, __cplusplus макрос — это не просто то, что компилятор начинает с определения перед передачей управления вам; это неизменная константа, которая не может быть изменена и является ошибкой при попытке изменить.

Что касается того, будет ли это хорошим подходом, если это возможно: зависит от контекста, но, вероятно, нет. Такого рода «дураки в заголовке» хаки (#define private publicкто-нибудь?) редко эффективны и никогда не безопасны.

РЕДАКТИРОВАТЬ: О, также, кстати, даже если у вас есть макрос, который было законно сохранять / восстанавливать, это не будет правильным способом сделать это. Увидеть Могу ли я переопределить макрос C ++ и определить его обратно?.

4

Это потому что __cplusplus предварительно определено компилятором.

Технически, это препроцессор, который определяет их, но в зависимости от того, какой компилятор вызывает препроцессор, выходные данные могут отличаться. Попробуйте запустить это:

$ g++ -dM -E - </dev/null

Выходные данные — все, что препроцессор определяет, что (в этом случае) производит препроцессор, выполняемый этой командой.

Имейте в виду __cplusplus там не появляется. Он встроен в каждый модуль компиляции C ++.

(То же самое работает при замене clang++ за g++.)

1
По вопросам рекламы [email protected]