çpreprocessor基于一个参数宏观专业化

问题描述:

是否有可能有一个不同的宏观扩展了一个具体的参数值,并以不同的方式,所有其它参数?

Is it possible to have one macro expanded differently for one specific argument value and differently for all other arguments?

说我定义当前用户:

#define CURRENT_USER john_smith

我希望能够做的是有一个宏,将的扩展的不同,如果用户通过匹配 CURRENT_USER 。你要知道,我不知道所有可能的用户的先验。最基本的情况:

What I want to be able to do is to have a macro that will be expanded differently if user passed matches CURRENT_USER. Mind you that I don't know all possible user 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 macro like that every other macro relying on the username could be done 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

这可能吗?

编辑:让我澄清一下。说每个程序员定义自己的配置定义不同 CURRENT_USER 。我想用户特定的宏exand为有意义当且仅当它们的用户参数匹配 CURRENT_USER 。因为我想这些宏包含 _Pragma 的IT不能运行时检查。

Let me clarify. Say each programmer defines different CURRENT_USER in their config header. I want user specific macros to exand to something meaningful if and only if their user argument matches CURRENT_USER. As I would like those macros to contain _pragmas it can't be runtime check (as proposed in some anwsers below).

编辑:再次澄清。说有宏禁用code部分路段的优化:

Again, clarification. Say there's macro to disable optimisation of some sections of code:

#define TURN_OPTIMISATION_OFF __pragma optimize("", off)

一些程序员要关闭优化功能为code的不同部分,但不是全部在同一时间。我想是有一个宏:

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 */

这将匹配 CURRENT_USER 宏,每程序员配置文件采取用户参数。如果用户匹配宏被扩展成编译。如果没有,不了了之。

That will match user argument against CURRENT_USER macro, taken from per-programmer config file. If the user matches macro is expanded into pragma. If not, to nothing.

大桶出来的可以。此anwser基于帕兹宏,但更简单的,并且不需要定义为每个用户。

Tuns out it is possible. This anwser is based on Pauls macros, but much simpler and does not need 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 

现在,因为MSVC错误我不得不修改检查宏位。

Now, because of the MSVC bug I had to modify 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

而不是定义 CURRENT_USER

我切换到下列宏。

Instead of defining CURRENT_USER I switched to 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

它实际上提供了更多的灵活性,因为可以同时使多个用户。括号是必需的。下面居然宏检测,是否 ENABLE_USER_<使用者方式> 扩展成括号与否

#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 a childs 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

有了这个宏观和 IIF (感谢保罗!)我决定执行原来的问题中提到的优化宏:

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

感谢您的输入!

编辑:这里的GCC版本: http://ideone.com/129eo

here's the GCC version: http://ideone.com/129eo