Отменить и переопределить макрос __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: Как вы думаете, это хороший подход?
3 ответа
Вопрос 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++
.)