The C/C++ preprocessor expands a nested macro only when the subsuming macro is expanded, as opposed to defined. It also allows macros to be redefined. This leads to an elegant and powerful technique, not used nearly widely enough, for eliminating unmaintainable duplications. The problem originates in C's divergent (tetrapartite, to be precise) syntactic namespace:
- Aggregates (names of structs, unions, and enums)
- Members within each aggregate
- Ordinary identifiers
It can be difficult to ensure bijections defined between, say, the members of an enumeration and two mutually-exclusive constant, statically-initialized arrays of structures remain preserved across changes to the code. This is, of course, the central problem of duplication. Eliminating the redundancy seems impossible (without explicitly-coded runtime checks, and the associated assurance problems and performance penalties): Designated initializers can ensure that reorderings are preserved and that deletions result in compilation failures, but they fail to address augmentations in any one set; the bijection can be violated when members are added.
Check section 2.4.3 of "How to Write Shared Libraries" by glibc maintainer Ulrich Drepper. The "Arrays of Data Pointers" solution provided therein is optimal for constant strings of common length, but an unmaintainable eyesore. X macros address this problem exquisitely. I was going to write up a solution, until I realized Appendix B of aforementioned paper already contains one, credited to Bruno Haible. Well, there you go.
- The New C: X Macros Dr. Dobb's 2001-05-01