This is not a pure specific check, but we can fully verify the specific token name.
Annotation of the first decision of principles based on Cloak by Paul Fultz II:
First, indicate the ability to conditionally select text based on macro expansion to 0 or 1
#define IIF(bit) PRIMITIVE_CAT(IIF_, bit) #define IIF_0(t, f) f #define IIF_1(t, f) t
Basic concatenation
Logical operators (compliment and and)
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) #define COMPL_0 1 #define COMPL_1 0 #define BITAND(x) PRIMITIVE_CAT(BITAND_, x) #define BITAND_0(y) 0 #define BITAND_1(y) y
A way to check if the token is or is not a parser "()"
#define CHECK_N(x, n, ...) n #define CHECK(...) CHECK_N(__VA_ARGS__, 0, ) #define PROBE(x) x, 1, #define IS_PAREN(x) CHECK(IS_PAREN_PROBE x) #define IS_PAREN_PROBE(...) PROBE(~)
Note. IS_PAREN works because "IS_PAREN_PROBE X" is included in one argument in CHECK (), where "IS_PAREN_PROBE ()" turns into PROBE (~), which turns into ~, 1. At this point, we can pick 1 from CHECK
Another utility to eat the necessary macros
#define EAT(...)
Here we use the blue picture (a thing that prevents naively recursive macros) to check if the two tokens are the same. If they fall on (). Otherwise, no, which we can detect through IS_PAREN.
It depends on existing COMPARE_XXX authentication macros for any given character.
#define PRIMITIVE_COMPARE(x, y) IS_PAREN(COMPARE_##x(COMPARE_##y)(()))
We are adding the IS_COMPARABLE flag for this helper.
#define IS_COMPARABLE(x) IS_PAREN(CAT(COMPARE_, x)(()))
We work back to EQUAL, checking to see if both arguments are matched and then converted to primitive_compare, if any. If not, we are not equal and eat the following arguments.
#define NOT_EQUAL(x, y) \ IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y))) \ (PRIMITIVE_COMPARE, 1 EAT)(x, y)
EQUAL is a compliment
#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y))
And finally, the macro that we really want.
First we will enable the comparison for "BUILDING_LIB"
#define COMPARE_BUILDING_LIB(x) x
Then our actual deciding macro, which is an integer, if on whether the symbol "BUILDING_LIB" is allowed
#define YES_IF_BUILDING_LIB(name) IIF(EQUAL(name, BUILDING_LIB))("yes", "no") #include <iostream> #define FOO BUILDING_LIB int main(int, char**) { std::cout << YES_IF_BUILDING_LIB(FOO) << "\n"; std::cout << YES_IF_BUILDING_LIB(BAR) << "\n"; }
What outputs:
yes no
Check out his great blog post (which I cut): C Tricks, Tips, and Preprocessor Idioms