A macro definition cannot include preprocessor directives (anything beginning with a #
).
To conditionally expand to certain values requires rather involved macrology and might not always work out the way you want. The example above could be written something like this:
#define ONE_OR_TWO(...) ONE_OR_TWO_(__VA_ARGS__, 2, 1,)
#define ONE_OR_TWO_(_1, _2, X, ...) X
#define CAT(A, B) CAT_(A, B)
#define CAT_(A, B) A ## B
#define M(N) CAT(IF_, ONE_OR_TWO(CAT(IS_, N)))({\
code; \
code; \
}, N)
#define IS_5 ,
#define IF_1(A, B) B
#define IF_2(A, B) A
M(5); //-> { code; code; }
M(8); //-> 8
This is incredibly fragile though. You can only use certain types of expression as the argument to M
, for instance - they have to have a syntactic structure that allows for concatenation, and no unwrapped commas - and it only works for predetermined values (e.g. to compare against something more complicated than a simple number is not possible with this method, because you can't build a macro name out of a more complex expression).
But in principle, it can be done. You just need thousands upon thousands of lines of macro definitions to cover a useful set of cases beyond the trivial ones like this. You can get those by using a metaprogramming library like Order-PP or Boost.Preprocessor, but be prepared for obscure error messages if you slip up in the syntax even slightly.