Я хочу отменить и переопределить макрос __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;
}
__cplusplus
но работает с AA
Я знаю, что это действительно ужасно, но причина, по которой я не определяю макрос, заключается в том, что я использую стороннее ПО, где они не используют #ifdef __cplusplus
Я имею в виду содержание #ifdef __cplusplus ... #endif
неправильно. Поэтому вместо того, чтобы менять их программное обеспечение, я решил сделать следующее
#define TEMP_VERSION __cplusplus
#undef __cplusplus
#include <third_party_sw.h>
#define __cplusplus TEMP_VERSION
Вопрос 1: Почему он не работает с __cplusplus, но работает с AA
Так как __cplusplus
является предопределенным макросом, и поведение (не) его определения не определено:
стандартный черновик [cpp.predefined]
Если какое-либо из предварительно определенных имен макросов в этом подпункте или определенный идентификатор являются предметом директивы предварительной обработки #define или #undef, поведение не определено. …
AA
не является предопределенным макросом, и идентификатор не зарезервирован. Можно (пере) определить его.
Вопрос 2: Как вы думаете, это хороший подход?
(Пере) определение зарезервированных идентификаторов никогда не является хорошим подходом. Даже переопределение пользовательских макросов является сомнительным предложением.
Идеальным подходом может быть исправление стороннего программного обеспечения, если это возможно. Кроме того, вы можете написать собственный заголовок для программного обеспечения, у которого нет проблем.
Из стандарта C ++ ([cpp.predefined, 3-4]):
Значения предопределенных макросов (кроме
__FILE__
а также__LINE__
)
оставаться неизменным на протяжении всего перевода. Если какой-либо из
предварительно определенные имена макросов в этом подпункте или определенный идентификатор,
является предметом директивы предварительной обработки #define или #undef,
поведение не определено.
Другими словами, __cplusplus
макрос — это не просто то, что компилятор начинает с определения перед передачей управления вам; это неизменная константа, которая не может быть изменена и является ошибкой при попытке изменить.
Что касается того, будет ли это хорошим подходом, если это возможно: зависит от контекста, но, вероятно, нет. Такого рода «дураки в заголовке» хаки (#define private public
кто-нибудь?) редко эффективны и никогда не безопасны.
РЕДАКТИРОВАТЬ: О, также, кстати, даже если у вас есть макрос, который было законно сохранять / восстанавливать, это не будет правильным способом сделать это. Увидеть Могу ли я переопределить макрос C ++ и определить его обратно?.
Это потому что __cplusplus
предварительно определено компилятором.
Технически, это препроцессор, который определяет их, но в зависимости от того, какой компилятор вызывает препроцессор, выходные данные могут отличаться. Попробуйте запустить это:
$ g++ -dM -E - </dev/null
Выходные данные — все, что препроцессор определяет, что (в этом случае) производит препроцессор, выполняемый этой командой.
Имейте в виду __cplusplus
там не появляется. Он встроен в каждый модуль компиляции C ++.
(То же самое работает при замене clang++
за g++
.)