Is it possible to have one macro expanded differently for one specific argument value and differently for all other arguments?
Say I define a current user:
#define CURRENT_USER john_smith
What I want to be able to do is to have a macro that will be expanded differently if the user passed matches CURRENT_USER
. Mind you, I don't know all possible users a priori. The most basic case:
#define IS_CURRENT_USER(user) \
/* this is not valid preprocessor macro */ \
#if user == CURRENT_USER \
1 \
#else \
0 \
#endif
With a macro like that, every other macro relying on the username could be done the following way:
#define SOME_USER_SPECIFIC_MACRO(user) SOME_USER_SPECIFIC_MACRO_SWITCH_1(IS_CURRENT_USER(user))
#define SOME_USER_SPECIFIC_MACRO_SWITCH_1(switch) SOME_USER_SPECIFIC_MACRO_SWITCH_2(switch) // expand switch ...
#define SOME_USER_SPECIFIC_MACRO_SWITCH_2(switch) SOME_USER_SPECIFIC_MACRO_##switch // ... and select specific case
#define SOME_USER_SPECIFIC_MACRO_0 ... // not current user
#define SOME_USER_SPECIFIC_MACRO_1 ... // current user
Is this possible?
EDIT: Let me clarify. Say each programmer defines a different CURRENT_USER
in their config header. I want user-specific macros to expand to something meaningful if and only if their user
argument matches CURRENT_USER
. As I would like those macros to contain _pragma
s, it can't be runtime check (as proposed in some answers below).
EDIT: Again, clarification. Say there's a macro to disable the optimisation of some sections of code:
#define TURN_OPTIMISATION_OFF __pragma optimize("", off)
Some programmers want to turn optimisation off for different sections of code but not all at one time. What I'd like is to have a macro:
#define TURN_OPTIMISATION_OFF(user) /* magic */
That will match the user
argument against the CURRENT_USER
macro, taken from the per-programmer config file. If the user matches, the macro is expanded into pragma. If not, to nothing.
It turns out it is possible. This answer is based on Paul's macros, but it is much simpler and does not need a definition for each user.
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define PROBE(x) x, 1
Now, because of the MSVC bug, I had to modify the CHECK
macro a bit.
#define MSVC_VA_ARGS_WORKAROUND(define, args) define args
#define CHECK(...) MSVC_VA_ARGS_WORKAROUND(CHECK_N, (__VA_ARGS__, 0))
#define CHECK_N(x, n, ...) n
Instead of defining CURRENT_USER
, I switched to the following macros.
#define ENABLE_USER_gwiazdorrr () // gwiazdorrr is now enabled
#define ENABLE_USER_foo () // foo is also enabled
// #define ENABLE_USER_bar () // bar is NOT enabled
It actually gives more flexibility because one can enable multiple users at the same time. The parenthesis is required. The macros below actually detect, whether ENABLE_USER_<user>
is expanded into parenthesis or not.
#define USER_ENABLED_PROBE(user) USER_ENABLED_PROBE_PROXY( ENABLE_USER_##user ) // concatenate prefix with user name
#define USER_ENABLED_PROBE_PROXY(...) USER_ENABLED_PROBE_PRIMIVIE(__VA_ARGS__) // expand arguments
#define USER_ENABLED_PROBE_PRIMIVIE(x) USER_ENABLED_PROBE_COMBINE_##x // merge
#define USER_ENABLED_PROBE_COMBINE_(...) PROBE(~) // if merge successful, expand to probe
USER_ENABLED_PROBE(gwiazdorrr) // expands to ~, 1
USER_ENABLED_PROBE(bar) // expands to USER_ENABLED_PROBE_COMBINE_bar
From now it is child's play:
#define IS_USER_ENABLED(user) CHECK(USER_ENABLED_PROBE(user))
IS_USER_ENABLED(gwiazdorrr) // expands to 1
IS_USER_ENABLED(bar) // expands to 0
Having this macro and IIF
(thanks Paul!) I decided to implement the optimisation macro mentioned in the original question:
#define TURN_OPTIMISATION_OFF(user) IIF( IS_USER_ENABLED(user) ) \
(\
__pragma optimize("", off),\
/* nothing */ \
)
TURN_OPTIMISATION_OFF(gwiazdorrr) // expands into __pragma optimize("", off)
TURN_OPTIMISATION_OFF(foo) // expands into __pragma optimize("", off)
TURN_OPTIMISATION_OFF(bar) // nothing emitted
Thanks for input!
EDIT: here's the GCC version: http://ideone.com/129eo