0

Suppose I have a file I can #include that defines something like this:

#define GROUP_NUMBER_FOO 42
#define GROUP_NUMBER_BAR 37

I would like to #define a macro that if invoked like this

GROUPID(FOO)(x);
GROUPID(BAR)(x);

is transformed to

GROUP42_ELEMENT_FOO(x);
GROUP37_ELEMENT_BAR(x);

I am hoping this can be done with token-pasting (as in Nested ## operator in C Preprocessor or How to concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?) but I can't seem to figure out how to do it.

Something like

#define EXTRACT_GROUP(name) GROUP_NUMBER_##name
#define GROUPID(name) GROUP##EXTRACT_GROUP(name)##_ELEMENT_##name

but if I try using GROUPID(FOO) then I get an error:

 error: pasting ")" and "_ELEMENT_" does not give a valid preprocessing token

(Before someone says "XY problem!" I have some existing awkward APIs I'm trying to adapt to in a more sensible way.)

Jason S
  • 184,598
  • 164
  • 608
  • 970

1 Answers1

0

Aha, I stumbled my way through it; it looks like I need to add an extra level of indirection:

#define GROUP_NUMBER_FOO 42
#define GROUP_NUMBER_BAR 37

#define CONCAT(x,y) x##y
#define EVALCAT(x,y) CONCAT(x,y)
#define CONCAT4(x,y,z,w) x##y##z##w
#define EVALCAT4(x,y,z,w) CONCAT4(x,y,z,w)
#define EXTRACT_GROUP(name) CONCAT(GROUP_NUMBER_,name)
#define GROUPID(name) EVALCAT4(GROUP,EXTRACT_GROUP(name),_ELEMENT_,name)

GROUPID(FOO)
GROUPID(BAR)

which gets transformed to the desired

GROUP42_ELEMENT_FOO
GROUP37_ELEMENT_BAR
Jason S
  • 184,598
  • 164
  • 608
  • 970