Have you ever wanted to write a “for each” loop over all the args of a variadic macro? Or have you ever wanted to overload a macro on the number of arguments? (If you’re saying to yourself, “good grief, why?” — I’ll describe a use case at the bottom of this post.)
I learned how to do this today, and I wanted to blog about it to cement the technique in my own mind.
Simple variadic macros
The first piece of magic you need to do something like this is
__VA_ARGS__. This allows you to write macros that take an arbitrary number of arguments, using
... to represent the macro’s parameters:
__VA_ARGS__ is a standard feature of C99, and I’ve known about it for a long time. I’ve also known about GCC (and Clang’s) extension, which attaches special meaning to
##__VA_ARGS__ if it’s preceded by a comma–it removes the comma if
##__VA_ARGS__ expands to nothing. If I change my macro definition to:
…I can now call
eprintf("hello, world"); without a complaint from the compiler.
But it’s not enough
That doesn’t let me do a “for each” loop, though. All the args that I pass are expanded, but I can’t do anything with them, individually. I have no names for my macro’s parameters–just the anonymous ….
I went poking around, not expecting to find a solution, but I was pleasantly surprised.
The “paired, sliding arg list” trick
The next building block we need is a technique that uses two complementary macros plus
__VA_ARGS__ to select something specific out of a macro arg list of unknown size. I found it in an answer on stackoverflow.com, and you can parse it all out directly from there, but the magic’s a little opaque. Here’s an explanation that takes it one step at a time:
See how it works? The first macro,
_GET_NTH_ARG(), takes any number of args >= N, but always returns item N (in this case, N=5). The second macro,
COUNT_VARARGS(...), takes an arbitrary number of args < N, pads with candidate values it wants to extract, and uses its args to call
_GET_NTH_ARG() in a way that puts the right candidate value in the known N position. In this case, the meaningful piece of info that we want in position N is an arg count; we’ve provided the values
4, 3, 2, 1 as candidate values, and one of those values will be in position N on expansion.
Tweaking this macro pair to handle a different N is a matter of adjusting what comes before N in the first macro, and what comes after
__VA_ARGS__ in the second macro. I’ll leave that as an exercise for the reader. :-)
We don’t have to select a numeric count with this technique; we could use it to select arg names with the
# operator, or even other macros. This will come in handy in a moment. But first, let’s address one shortcoming:
COUNT_VARARGS(...) doesn’t handle the case of zero args. Here’s the fix:
Now, we can build on this to define a variadic macro that has an expansion overridden by how many args it receives. This is what the original stackoverflow answer did. Something like this:
Now we’re getting close to being able to code a “for each” loop over all the args to a variadic macro. If the macro that gets overridden has a “for each” flavor, it all comes together:
Okay, but why?
I said I’d provide some explanation of why this technique could be useful. In general, I am not a fan of macros rewriting the syntax of a programming language; that can obscure what’s really happening, and make for a steeper learning curve.
On the other hand, sometimes they are really helpful. They can make code much less verbose/repetitive by eliminating noise and boilerplate. Occasionally, I run into cases where that tradeoff seems worth it to me.
More importantly, macros have a property that you can’t get any other way–the same fragment of code can have multiple meanings, and can maintain this semantic parallelism without being susceptible to human memory errors, laziness, or misunderstanding. I have previously blogged about how valuable this can be in eliminating encapuslation problems with enums, but I recently found another need for it. In my project to create a new programming language, I have to create some foundation packages and classes — the analog to
java.lang in java, or
My in .NET. This foundation needs to written in C/C++ to avoid a chicken-and-egg problem. That means I need some way to use namespaces, classes, and other C++ constructs in the source code, but also generate package and class constructs visible to my
intent compiler. Macros were an obvious answer.
The only problem was that some of my macros needed to be variadic–and I needed for-each-style semantics. Hence my research. :-)
How about you? Have you ever had a need for something like this?