Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C++20, is a macro considered "active" if it's #undef'd, then #define'd again?

Consider

#define VER 1
#undef VER
#define VER 2

#if defined(VER) // #1
#error VER is defined 
#endif

[cpp.import]/6:

A macro directive is active at a source location if it has a point of definition in that translation unit preceding the location, and does not have a point of undefinition in that translation unit preceding the location.

My understanding is that VER has a point of undefinition preceding #1 (the #undef VER), and thus it is not considered active. That is, defined(VER) should expand to 0, and the #error directive should not be in effect.

But in practice, all compilers produce an error saying VER is defined (which agrees with my intuition, but not with my understanding of the standard).

Is my understanding incorrect? What did I miss?

like image 463
cpplearner Avatar asked Feb 25 '21 10:02

cpplearner


Video Answer


1 Answers

Let's see if I can lawyer that.

The paragraphs above where the link points say:

  1. Each #define directive encountered when preprocessing each translation unit in a program results in a distinct macro definition.

So, #define VER 1 is a definition, and #define VER 2 is a distinct one.

5.1 The point of definition of a macro definition within a translation unit is the point at which its #define directive occurs

Both have a point of definition, obviously.

5.2 The point of undefinition of a macro definition within a translation unit is the first point at which a #undef directive naming the macro occurs after its point of definition, [...]

And #define VER 1 has a point of undefinition, while #define VER 2 doesn't.

Therefore, the macro definition of #define VER 2 is active at the location of the test. At some earlier points, #define VER 1 would be active instead.


Then again, if you were to do this:

#define X 1
#define X 2
#undef X

/* is X active now ??? */

There wouldn't seem to be a "point of undefinition" for the first #define, but I think you'd run afoul of

7 If a macro would be replaced or redefined, and multiple macro definitions are active for that macro name, the active macro definitions shall all be valid redefinitions of the same macro

because they're not the same macro. (There's examples in the cpp.replace page.) Though GCC and Clang accept that with a warning, with the obvious semantics of redefining it with the new value (and not e.g. stacking the definitions so that #undef would only remove one -- that way lies madness.)

like image 175
ilkkachu Avatar answered Oct 14 '22 02:10

ilkkachu