Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Preprocessor to split "int x" into int & x

I need to be able to get the following:

#define MY_MACRO(PARAM1,PARAM2) \
 MY_OTHER_MACRO(TYPENAME_OF(PARAM1),PARAMNAME_OF(PARAM1));\
 MY_OTHER_MACRO(TYPENAME_OF(PARAM2),PARAMNAME_OF(PARAM2));\

to cause

MY_MACRO(int x,char *z) 

to compile as

MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char*,z);

or it would not be the end of the world if it compiled as:

MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,*z);

or even this would be ok too: (i can code MY_OTHER_MACRO to work with either result)

MY_OTHER_MACRO(int,x);
MY_OTHER_MACRO(char,z);

alternatively, if there is some way of counting the tokens that are separated by whitespace (and assume that "*" is separate token, i can work with that too - e.g. 2 vs 3) typically, tokens are separated by commas, as far as i know. is there any way to use another character?

like image 250
unsynchronized Avatar asked Nov 21 '13 12:11

unsynchronized


1 Answers

You can do this, but only with the extremely difficult limitation that you must know all of the type names in advance: it won't work with any user-defined types unless the user adds them to the list of known types too - that's admittedly not hard.

Accepting this limitation, you can do something like this:

#define LPAREN (
#define RPAREN )
#define COMMA ,

#define CAT(L, R) CAT_(L, R)
#define CAT_(L, R) L ## R
#define EXPAND(...) __VA_ARGS__

#define SPLIT(OP, D) EXPAND(OP CAT(SPLIT_, D) RPAREN)

#define SPLIT_int LPAREN int COMMA
#define SPLIT_char LPAREN char COMMA
#define SPLIT_float LPAREN float COMMA
#define SPLIT_double LPAREN double COMMA

#define MY_MACRO(A, B) \
SPLIT(MY_OTHER_MACRO, A); SPLIT(MY_OTHER_MACRO, B);

MY_MACRO(int x, char * z)  // emits MY_OTHER_MACRO ( int , x ); MY_OTHER_MACRO ( char , * z );

Adding a type to the list of known types is, as above, a one-liner (#define SPLIT_myType LPAREN myType COMMA), and can be done anywhere in the program as long as it comes before the type is actually used by SPLIT, so it's not the end of the world, although it is highly intrusive.

There is no easy way to get the asterisk to be on the left of the split. It could probably be done, but it would be much more complicated, and involve placing the restriction on the list of allowed variable names, which IMO is much, much worse. Probably more intrusive too, since you're almost certain to have more variables than types in a working program.

like image 57
Leushenko Avatar answered Oct 25 '22 19:10

Leushenko