C Preprocessor tricks, tips, and idioms
12 points by linkdd
12 points by linkdd
I saw an interesting trick at work recently. I removed a dependency on Mesa 3D by pulling out the tesselation API from libGLU into its own library which is a lot smaller and easier to work with.
While doing that, I noticed this trick it was using to share code between a heap priority queue and a sorted priority queue that uses the heap queue in its implementation.
In priorityq.h it has:
#define pqInit(pq) __gl_pqSortInit(pq)
#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
// ...
In the priorityq-heap.h:
#define pqInit(pq) __gl_pqHeapInit(pq)
#define pqInsert(pq,key) __gl_pqHeapInsert(pq,key)
// ...
And then in priorityq.c it #includes priorityq-heap.c to define the heap implementation before
#including priorityq-sort.h to redefine the pqInit and other macros into the sorted versions, followed by the sorted implementation using the newly redefined macros.
Unfortunately, I had to debug through it all because I had added priorityq-heap.c to the project as a source file, meaning it got passed into the compiler, when it's only supposed to be #included from priorityq.c.
The amount of concatenation/pasting that C Swiss Tables initially surprised me but I think the policy-based API is quite spiffy now.
https://github.com/google/cwisstable/blob/main/cwisstable/policy.h
The best preprocessor idiom is avoidance. Code is generally shorter and clearer without this advanced trickery.