2

I want to undefine and redefine the __cplusplus macro am getting however compilation error:__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;
}
  • Question 1: Why it is not working with the __cplusplus but works with AA

I know that this is really ugly but the reason why am undefining the macro is that I am using a third party Software where they are missusing the #ifdef __cplusplus, I mean the content of the #ifdef __cplusplus ... #endif is wrong. So instead of changing their software I choosed to do the following

#define TEMP_VERSION __cplusplus
#undef __cplusplus
#include <third_party_sw.h>
#define __cplusplus TEMP_VERSION
  • Question 2: What do you think is it a good approach ?
Mouin
  • 1,025
  • 4
  • 19
  • 33
  • 4
    Names that start with double underscores are reserved for the implementation. Technically this is UB. – NathanOliver Dec 10 '18 at 14:17
  • because 'AA' is defined as a number which is legal in the '<<' operator. you define __cplusplus as an arbitrary set of letters that gets resolved to nothing. '<<' has no idea what to do with it. – Serge Dec 10 '18 at 14:17
  • 1
    *"the content of the #ifdef __cplusplus ... #endif is wrong"* you should probably ask about a proper workaround then (giving some details on what is exactly wrong), right now this is a typical XY problem – user7860670 Dec 10 '18 at 14:23
  • *"It works with `AA`"* You're using `AA` differently. Consider: http://coliru.stacked-crooked.com/a/06065c268a7c2bff – HolyBlackCat Dec 10 '18 at 14:30

3 Answers3

5

From the C++ standard ([cpp.predefined, 3-4]):

The values of the predefined macros (except for __FILE__ and __LINE__) remain constant throughout the translation unit. If any of the pre-defined macro names in this subclause, or the identifier defined, is the subject of a #define or a #undef preprocessing directive, the behavior is undefined.

In other words, the __cplusplus macro isn't just something that the compiler starts out by defining before handing control over to you; it is an immutable constant, which cannot be changed and is an error to attempt to change.

As for whether it would be a good approach if it were possible: Depends on the context, but probably not. These sorts of "fool the header" hacks (#define private public, anyone?) are seldom effective and never safe.

EDIT: Oh, also incidentally, even if you did have a macro it was legal to save/restore, that wouldn't be the right way to do it. See Can I redefine a C++ macro then define it back?.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
1

It's because __cplusplus is pre-defined by the compiler.

Technically, it's the pre-processor that defines them, but depending on which compiler invokes the pre-processor, the output may differ. Try running this:

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

The output is all the pre-processor defines that (in this case) the pre-processor run by this command produces.

Mind you __cplusplus does not appear there. It's built-in for every C++ compilation unit.

(The same works when substituting clang++ for g++.)

  • "Mind you `__cplusplus` does not appear there. It's built-in for every C++ compilation unit." I think you're missing something. Your preprocessor, despite being invoked _from_ `g++`, is _not_ defining `__cplusplus` when invoked this way. Try `echo __cplusplus | g++ -EP -`. Compare to `echo __cplusplus>foo.cpp;g++ -EP foo.cpp`. – H Walters Dec 11 '18 at 02:39
  • @HWalters yes, I wrote that it does not appear there. Nitpicking sure is a great hobby, but it's not the kind of thing that would help the OP in this case. – Jens Finkhaeuser Jul 01 '19 at 12:17
1

Question 1: Why it is not working with the __cplusplus but works with AA

Because __cplusplus is a pre-defined macro, and behaviour of (un-)defining it is undefined:

stadard draft [cpp.predefined]

If any of the pre-defined macro names in this subclause, or the identifier defined, is the subject of a #define or a #undef preprocessing directive, the behavior is undefined. ...

AA is not a pre-defined macro, nor is the indentifier reserved. It is OK to (re-)define it.


Question 2: What do you think is it a good approach ?

(Re-)defining reserved identifiers is never a good approach. Even redefining user defined macros is a dubious proposition.

Ideal approach might be to fix the third party software, if possible. Alternatively, you could write a custom header for the software which doesn't have the problem.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326