On the one hand, I personally enjoy exercises like this, and the end result is quite pleasing to look at. On the other hand, the whole idea is kind of funny to me.<p>In my experience, a proclivity to programming serious low-level code in C very much comes with an intense defensive reaction to things like "metaprogramming using the C precompiler". At least I still vividly the remember my co-workers' reaction to the C code I wrote as an intern, when I tried to be clever.
I have thought a lot about meta programming and the best way to do it (I participate in the ISO C wg14) and I dislike macros, templets and every other attempt I have seen.<p>The best solution I have found, disregarding of language, is to use the same language to write a program that generates the code you need.<p>Then you can compile, and debug them separately using the same workflow, and each program can be clear and simple to read. Its not sexy or clever, but it works and anyone can understand what is going on. Almost always that turns out to be the most important thing.
<a href="http://libmill.org/" rel="nofollow">http://libmill.org/</a> “is in an active auction”.<p><a href="https://www.sav.com/auctions/details/1159199/libmill.org" rel="nofollow">https://www.sav.com/auctions/details/1159199/libmill.org</a><p>Insert some joke about the dangers of overly abusing the C precompiler…
Metaprogramming should be limited, and metaprogramming in C is quite brittle and almost nobody really understand the execution model of he preprocessor. But, dismissing the preprocessor outright is too quick a conclusion. There are some clever and very practical uses of the preprocessor.<p>- portability<p>- generate strings from identifiers<p>- Insert file and line of the call location (or other context) automatically when calling a function.<p>- X-macros<p>- Scopes with exit statement given at beginning,
hacked using "for" statement and a condition that
evaluates to true only the first time. A little bit
brittle when the exit statement must not be skipped (goto, return).<p>I'm sure there are more, but I'm too tired to think harder... Here is an example of the last category:<p><pre><code> #define TIMED_SECTION_(name, t) FOR_SCOPE(Timer t = start_timer(); print_passed_time(name, t))
#define TIMED_SECTION(name) TIMED_SECTION_(name, UNIQUE_NAME())
</code></pre>
Not giving the FOR_SCOPE() and UNIQUE_NAME() macros here for brevity. They add another 3-5 reusable lines. Use like this:<p><pre><code> TIMED_SECTION("foo the bar")
{
/* Do stuff, time spent in this scope will be measured and printed on scope exit. */
}
</code></pre>
Other more advanced languages can do some of the same things, sometimes more robustly, or not at all (X-macros is probably hard to replace for languages that are not LISP). But it typically comes at a cost in complexity, hard to use type systems, complicated semantics with edge cases... And they only allow you to do what is already built into the language!
> However, such syntax is ugly and verbose.<p>Is it just me who thinks this was by far the clearest, cleanest formulation? Everything following it seemed to sacrifice clarity for the sake of cleverness.<p>Also I really dislike macros that try to disguise themselves as "not macros". Capitalise the crap out if it, make the fact that this is a macro stand out, man!