3

Suppose that, in C, I have an list of things specified using X-macros. For example,

#define TYPES(X, ...) \
  X(__VA_ARGS__, i, int) \
  X(__VA_ARGS__, j, unsigned int) \
  X(__VA_ARGS__, l, long) \
  X(__VA_ARGS__, m, unsigned long)

If I add a second copy of that macro (call it TYPES_), it’s not hard to generate some code for each pair of things in the list; for example:

#define TYPES_(X, ...) \
  X(__VA_ARGS__, i, int) \
  X(__VA_ARGS__, j, unsigned int) \
  X(__VA_ARGS__, l, long) \
  X(__VA_ARGS__, m, unsigned long)
#define CAST(FROMCH, FROMTY, TOCH, TOTY) \
  TOTY FROMCH ## to ## TOCH (FROMTY x) { return (TOTY)x; }
TYPES_(TYPES, CAST)

However, if I use TYPES instead of the duplicate TYPES_, this code won’t work, because (I think?) the top-level expansion TYPES then contains an occurrence of TYPES itself, which is not permitted to expand further.

Is there a way to convince the C preprocessor to generate code for a cartesian product of a list with itself, like here, without specifying the list twice? It’s probably possible with chaos/order-pp-style insanity that accomplishes a lot of expansions through billion laughs-like hacks, but I’d prefer not to resort to that.

Alex Shpilkin
  • 776
  • 7
  • 17
  • 2
    See [Can we have recursive macros?](https://stackoverflow.com/a/12540675/2402272). The top-voted answer demonstrates a way to expand a macro an arbitrary (but fixed) number of times. It looks like that would serve your purposes. – John Bollinger Mar 17 '23 at 23:18

1 Answers1

4

You can use an EXPAND macro to perform delayed expansion. Rather clumsily:

#define EXPAND(X) X
#define TYPES1() TYPES
#define TYPES2(...) TYPES1 EXPAND(())(__VA_ARGS__)
EXPAND(TYPES(TYPES2, CAST))

Demo.

ecatmur
  • 152,476
  • 27
  • 293
  • 366