Reputation: 69964
Is there a way to write a C preprocessor macro that expands to different things depending on what argument it receives?
#define foo() ???
/* 1 */
foo(name)
/* 2 */
foo(_)
Desired result:
/* 1 */
int name;
/* 2 */
/*ignore*/
Yes, I know macros are evil. I'm asking this mostly out of curiosity.
Upvotes: 15
Views: 9590
Reputation: 1736
With the tricks described here, it is possible to do what you want at compile time.
You could use the EQUAL
macro defined at the end of the document, and do this:
#define COMPARE__(x) x
#define OPTION_0(x) int x;
#define OPTION_1(x) /* nothing */
#define foo(x) CAT(OPTION_, EQUAL(_, x))(x)
foo(name1) // int name1;
foo(_) // /* nothing */
foo(name2) // int name2;
Upvotes: 3
Reputation: 13390
To expand on Gavin Smith's answer, you actually can check conditions within a macro expansion:
#define FOO_name 1
#define FOO__ 0
#define CONC(a,b) a##_##b
#define IF(c, t, e) CONC(IF, c)(t, e)
#define IF_0(t, e) e
#define IF_1(t, e) t
#define FOO(x) IF(CONC(FOO,x), int x;, )
FOO(name) // -> int name;
FOO(_) // -> /*nothing*/
If you're feeling adventurous you can easily extend IF
to allow commas, suppress macro expansion, etc. with helper macros.
As above though this does require that you know all of the desired names in advance.
Upvotes: 17
Reputation: 3154
Perhaps try some multi-stage macro expansion? This is the strategy used by the Boost preprocessor/control/if library.
#define FOO_NAME 1
#define FOO__ 2
#define CONC(a,b) a##_##b
#define FOO(x) CONC(FOO,x)
I don't think there is any way to check conditions within a C macro expansion.
The best thing I could come up with is to covert the macro arguments to a string literal using the #
stringizing operator, and then checking using run-time functions. (This won't work for your case, though, where you want to output variable declarations.)
For example, the following prints "011":
#define FOO(x) (strcmp("NAME", #x) ? 1 : 0)
main()
{
printf("%d", FOO(NAME));
printf("%d", FOO(1));
printf("%d", FOO(2));
}
The compiler would likely optimize the strcmp
comparisons at compile-time so it would be no more inefficient than it would have been had genuine pre-processor conditionals been available. However, making FOO
a normal function would be clearer and probably just as efficient.
Upvotes: 9