0
votes

I am using Preprocessor Directives to define function macros in C. Can I have multiple if/else if statements in a function macro?

If yes how do I write it?

#define WRITE(str,id) #str(id)

// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if type==1 WRITE(draw_text,windowID) else if type==2 WRITE(draw_image,windowID) else if type==3 WRITE(draw_hyperlink,windowID)

// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);

// At compile time the above should be converted to...
draw_text(112);
draw_image(178);
draw_hyperlink(988);

I am aware how to perform a single if else statement in a Function Macro but not how to do it with multiple if/else if's:

// if else eg
#define DRAW_GENERIC_WINDOW(windowID, type) ((type)==(1))?WRITE(draw_text,windowID):WRITE(draw_image,windowID)

Note: Before you ask "Why the hell are you programming like this?" :P its because I am writting in a language that is very similar to C called 4dm, except there are no structs, pointers or the ability to declare new data types. So I am forced to resort to Preprocessor Directives in order to achieve some form of virtual functions(used when I dont know the type of window - image, hyperlink, etc. - that I am working with).

2
you should be able to expand that macro with as many if-else-if-else-if... you want. noted: glad I'm not the one debugging a DRAW_GENERIC_WINDOW() expansion, esp if you draw that out a dozen or more clauses.WhozCraig
Why the pound "#" character before str? #define WRITE(str,id) #str(id) Shouldnt that be #define WRITE(str,id) str(id)imreal

2 Answers

3
votes

Try it out like this:

#define WRITE(str,id) str(id)

// HERES where I am having difficulty
#define DRAW_GENERIC_WINDOW(windowID, type) if (type==1) \
WRITE(draw_text,windowID) \
else if (type==2) \
WRITE(draw_image,windowID) \
else if (type==3) \
WRITE(draw_hyperlink,windowID)

// usage
DRAW_GENERIC_WINDOW(112, 1);
DRAW_GENERIC_WINDOW(178, 2);
DRAW_GENERIC_WINDOW(988, 3);
1
votes

Just use the token pasting operator ## as basic pattern matching, like this:

#define DRAW_GENERIC_WINDOW(windowID, type) DRAW_GENERIC_WINDOW_ ## type(windowID)

#define DRAW_GENERIC_WINDOW_1 draw_text
#define DRAW_GENERIC_WINDOW_2 draw_image
#define DRAW_GENERIC_WINDOW_3 draw_hyperlink

Then use it like this:

DRAW_GENERIC_WINDOW(112, 1); // expands to draw_text(112, 1);
DRAW_GENERIC_WINDOW(178, 2); // expands to draw_image(178);
DRAW_GENERIC_WINDOW(988, 3); // expands to draw_hyperlink(988);