Reputation: 16165
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?
Upvotes: 15
Views: 37208
Reputation: 195
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
.
Upvotes: 0
Reputation: 263177
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.
Upvotes: 7
Reputation: 39551
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.
Upvotes: 18