简体   繁体   中英

Is it possible to compare #ifdef values for conditional use

I'm trying to come up with a generic, easy to use way to only run certain code, depending upon the api I am using at the time.

In a header:

#define __API_USED cocos2d-x

#define COCOS2DX  cocos2d-x
#define OPENGL opengl

#ifdef __API_USED == COCOS2DX
    #define USING_COCOS2DX
    #undef USING_OPENGL
#endif

in source:

#ifdef USING_COCOS2DX
    ......
#endif

However I don't think this would work.

Is there a way to accomplish what I am looking to do?

You can but you need to do it like this:

#define __API_USED COCOS2DX

#define COCOS2DX  1
#define OPENGL 2

#if __API_USED == COCOS2DX
    #define USING_COCOS2DX
    #undef USING_OPENGL
#endif

As Keith Thompson explained undefined tokens (macros) like cocos2d and x evaluate to 0 so you need to define values for the macros you're using.

If I understand this correctly, cocos2d-x is one of several possible APIs.

The preprocessor can test whether a symbol is defined or not (using #ifdef and the defined operator), and it can evaluate constant integer expressions (using #if ).

One approach would be to define a numeric code for each API:

#define COCOS2X         1
#define ANOTHER_API     2
#define YET_ANOTHER_API 3
/* ... */

and then:

#define API_USED COCOS2DX
#if API_USED == COCOS2DX
    #define USING_COCOS2DX
    #undef USING_OPENGL
#elif API_USED == ANOTHER_API
    /* ... */
#elif API_USED == YET_ANOTHER_API
    /* ... */
#endif

Note that I've changed your macro name __API_USED to API_USED . Identifiers starting with two underscores (or with an underscore followed by an uppercase letter) are reserved to the implementation for all purposes; you shouldn't define them in your own code.

One drawback of this approach is that misspellings won't be flagged; the preprocessor quietly replaces any undefined identifiers with the constant 0 .

It's probably better to have an identifier for each API, and define it if and only if that API is being used:

#define USING_COCOS2X
/* #undef USING_COCOS2X */

and then:

#if USING_API_COCOS2X
    #undef USING_OPENGL
#endif

Testing whether a macro is defined or not tends to be more robust than testing whether it has a specific value.

You then just have to make sure that the USING_API_* macros (if there are several) are defined consistently.

This works for me with clang 8.1.0 (from Xcode 8.3.2). Suppose, in a header file, we want to test CONFIG for the value special . In any given translation unit, CONFIG might be unset, or might be set to special , or might be set to something else.

#define CAT_HELPER(lhs, rhs) lhs##rhs
#define CAT(lhs, rhs) CAT_HELPER(lhs, rhs)

#define TEST_PREFIX_special 1

#if CAT(TEST_PREFIX_, CONFIG)
#pragma message("detected CONFIG == 'special'")
#else
#pragma message("CONFIG != 'special'")
#endif

The double indirection ( CAT() calls CAT_HELPER() ) is important.

This tactic relies on #if expanding an undefined macro as 0 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM