C/C++ Macro expansion vs. Code generation
-
05-07-2019 - |
Question
Both Macro expansion & Code generation have pros & cons. What's your favorite approach and why? When should we choose one over the other? Please kindly advise. Thank you!
Macro expansion can be very handy & helpful: http://dtemplatelib.sourceforge.net/table.htm
vs
While Code generation gives you plenty of nice code: http://code.google.com/p/protobuf/ http://incubator.apache.org/thrift/
Solution
It's a tradeoff. Let me give an example. I stumbled on the technique of differential execution around 1985, and I think it's a really good tool for programming user interfaces. Basically, it takes simple structured programs like this:
void Foo(..args..){
x = y;
if (..some test..){
Bar(arg1, ...)
}
while(..another test..){
...
}
...
}
and mucks with the control structure like this:
void deFoo(..args..){
if (mode & 1){x = y;}
{int svmode = mode; if (deIf(..some test..)){
deBar(((mode & 1) arg1 : 0), ...)
} mode = svmode;}
{int svmode = mode; while(deIf(..another test..)){
...
} mode = svmode;}
...
}
Now, a really good way to do that would have been to write a parser for C or whatever the base language is, and then walk the parse tree, generating the code I want. (When I did it in Lisp, that part was easy.)
But who wants to write a parser for C, C++, or whatever?
So, instead, I just write macros so that I can write the code like this:
void deFoo(..args..){
PROTECT(x = y);
IF(..some test..)
deBar(PROTECT(arg1), ...)
END
WHILE(..another test..)
...
END
...
}
However, when I do this in C#, somebody in their wisdom decided macros were bad, and I don't want to write a C# parser, so I gotta do the code generation by hand. This is a royal pain, but it's still worth it compared to the usual way of coding these things.
OTHER TIPS
For c++ I prefer either template metaprogramming or code generation over macros, but macros still have their uses.
The example you have given with dbtemplatelib could be covered with c++0x Variadic Templates, with additional benefits like type checking etc.
In C or C++, macro expansion is notoriously difficult to debug. On the other hand, writing a code generator is easier to debug because it's a separate program in itself.
However, you should be aware that this is merely a limitation of the C preprocessor. For example, in the Lisp family of languages, macro expansion is code generation, they're exactly the same thing. To write a macro, you write a program (in Lisp) to transform S-expression input into another S-expression, which is then passed to the compiler.
Both have their problems. Unlike macros, code generation can produce readable and debuggable (is that even a word?) code, but it is less flexible and harder to change.