I wrote a useful extension to the C preprocessor for GCC, and submitted it to the gcc-patches mailing list in April. This went unnoticed, as have my subsequent pings since. I'm planning to ping once a month from now on until the rest of 2022, and then switch to quarterly.
__EXP_COUNTER__ gives a macro expansion to a numeric value which uniquely enumerates that expansion.
The sister macro __UEXP_COUNTER__ allows a macro expansion to access the parent's value: if a macro is being expanded in the body of another macro, one level up, it provides the __EXP_COUNTER__ value of that parent macro.
This feature solves the problem of producing unique names in a macro. (Unique within a translation unit.)
The __LINE__ symbol gets abused for this. The problem is that it's not unique. A macro can be called two or more times in the same line of code. Moreover, the same line number like 42 can occur multiple times in the same translation unit due to #include; a line number is not unique within a translation unit.
__COUNTER__ is next to useless because on each access, its value changes. It's useful in a situation in which a name is needed syntactically, and has to be unique, but is otherwise never referenced: just mentioned once and that's it.
Multiple references to __EXP_COUNTER__ in the same macro expansion context produce the same value.
As someone who understands C macros relatively well and who makes frequent use of them, I don't think I understand what __EXP_COUNTER__ does, and how it is different from __COUNTER__. I would have to experiment each time before using it, and would then quickly forget again the intricate details about expansion order, etc., similar to how every time I do some kind of STRINGIFY macro I have to make sure to use the right number of forwarding macro calls.
Is there a concrete use case for this that really can't be solved by __LINE__? I've used __LINE__ in the past to generate unique identifiers used in macro-generated code chunks. I don't see that non-uniqueness thing you mentioned causing any problems except for global variables (so not really an issue in my book).
As much as I love the C preprocessor as a crude tool that can solve many practical issues that are solved in other languages with a magnitude more complexity (besides solving problems that other languages don't have), I think the value doesn't come from its unintelligible execution model. And if __EXP_COUNTER__ is so difficult to understand, I personally don't like it.
The parent comment explained pretty well the advantages over __LINE__ imo.
Crafting macros is often black magic, but using them shouldn't be (if they're well crafted). Having an implicit rule in your macro that it cannot be used twice in the same line is surprising and potentially dangerous.
Another example is where you have a macro doing lots of work, if it needs to use a submacro multiple times that itself needs a unique identifier, then __LINE__ is no longer sufficient.
__UEXP_COUNTER__ is a little more difficult to imagine a use-case for, I'll admit (I can see it allows passing counters around, but I can't see why a parameter couldn't do the same).
Again, preprocessor macros are black magic, these additions seem a lot simpler to understand than `__VA_OPT__` (and its predecessor `##__VA_ARGS__`) or MSVCs awful stringify problems, as you brought up.
__EXP_COUNTER__ has a stable value in a given token replacement sequence (right hand side of a macro).
__COUNTER__ __COUNTER__ __COUNTER__ might give you 42 43 44, whereas __EXP_COUNTER__ __EXP_COUNTER__ __EXP_COUNTER__ will produce 73 73 73.
We can imagine that every macro has a hidden parameter:
#define MAC(A, B, C, __EXP_COUNTER__)
we don't pass this parameter when calling the macro; the macro expander does that, and it passes an integer token whose value is incremented for each such call.
Right, but now you can't use that COUNTER value in a macro and have it stay the same value. Think about concatenating a variable name with the counter and trying to use that same new name later in the same macro. Like NAME ## __COUNTER = NAME ## __COUNTER -1; This won't work without some extra state.
This code won't work in any case. You can't do arithmetic like that. And I think it's much better code anyway to create the expansion once, because otherwise you have to construct NAME ## __COUNTER at each use and it quickly becomes unmaintainable and hard to change how you construct that name.
IMO the best solution if you want to avoid an extra indirection to inject some state, would be preprocessor variables that you can assign to in a macro expansion. Procedural preprocessor code basically. But the preprocessor doesn't work like that.
I'm probably missing something, but can't you use counter to generate a unique name once and then forward to to another macro so that it can be used multiple times?
Thus perhaps you may be able to get something like __EXP_COUNTER__ by splitting your macros into interface and implementation:
#define MAC_IMPL(A, B, EXP_COUNTER)
#define MAC(A, B) MAC_IMPL(A, B, __COUNTER__)
I'm guessing this is what you mean by forwarding.
This could be a pretty major inconvenience, if you have to do it in the middle of a situation that is already stuffed with preprocessing contortions. Like say you had to define 32 macros that are similar to each other, for whatever reason, and you want this hack: now you have 64.
By the way, I'm also interested in solving the "no recursive macro" problem hinted at in this submission. While working on __EXP_COUNTER__, I looked into it a bit.
The big issue is that the GNU C preprocessor uses global state for tracking expansion. In effect, it takes advantage of the no-recursion rule and says that during a macro's expansion, only one context for that expansion needs to exist. That context is patched into the macro definition, or something like that. (I don't have the code in front of me and it's been a few months.) The preprocessor knows that there is a current macro being expanded, and there is a stack of those; but that is referenced by its static definition, which has a 1:1 relationship to expansion state, like parameters, location and whatnot. That might have to turn into a stack, perhaps; there is a refactoring job there, and the code is a bit of a hornet's nest.
In terms of syntax/deployment, it would be easy. I envision that there could be a #defrec directive that is like #define, but which creates a macro that is blessed for recursive expansion. Or other possibilities: #pragma rec(names, of, macros, ...) which is better for code that has to work without the extension, since it uses #define.
Your NBDKIT_UNIQUE_NAME(name) cannot produce the same name twice because it doesn't take a counter as a parameter.
__EXP_COUNTER__ adds the ability for a macro expansion to have its own counter for that expansion instance, without some other macro having to hand it one as a an extra, visible parameter.
https://gcc.gnu.org/pipermail/gcc-patches/2022-April/593473....
__EXP_COUNTER__ gives a macro expansion to a numeric value which uniquely enumerates that expansion.
The sister macro __UEXP_COUNTER__ allows a macro expansion to access the parent's value: if a macro is being expanded in the body of another macro, one level up, it provides the __EXP_COUNTER__ value of that parent macro.
This feature solves the problem of producing unique names in a macro. (Unique within a translation unit.)
The __LINE__ symbol gets abused for this. The problem is that it's not unique. A macro can be called two or more times in the same line of code. Moreover, the same line number like 42 can occur multiple times in the same translation unit due to #include; a line number is not unique within a translation unit.
__COUNTER__ is next to useless because on each access, its value changes. It's useful in a situation in which a name is needed syntactically, and has to be unique, but is otherwise never referenced: just mentioned once and that's it.
Multiple references to __EXP_COUNTER__ in the same macro expansion context produce the same value.