Reputation: 6687
I have the following code:
#define FOO_BAR x
#define FOO(x) FOO_BAR
I do want FOO(2)
to expand to 2
, but I'm getting x
instead. I tried to use EXPAND
macro to force extra scan:
#define FOO_BAR x
#define EXPAND(x) x
#define FOO(x) EXPAND(FOO_BAR)
Note, this is intentional, that FOO_BAR
doesn't accept x
as an argument. Basically, I cannot pass x to FOO_BAR
.
But it doesn't work as well. Any ideas?
I want this to work on any compiler (MSVC, gcc, clang).
My end goal is to create type safe enums for OpenGL. So, I need to do mapping from my safe enum to unsafe ones. So I have something like:
enum class my_enum {
foo,
bar
}
GLenum my_enum2gl(my_enum e) {
switch (e) {
case my_enum::foo: return GL_FOO;
case my_enum::bar: return GL_BAR;
}
return GL_NONE;
}
Since I'm lazy, I did some preprocessor magic. And implemented this as:
#define PP_IMPL_ENUM_VALUE(enum_pair) __PP_EVAL(__PP_IMPL_ENUM_VALUE enum_pair)
#define __PP_IMPL_ENUM_VALUE(cpp_enum, gl_enum) cpp_enum,
#define PP_IMPL_CONVERT(enum_pair) __PP_EVAL(__PP_IMPL_CONVERT enum_pair)
#define __PP_IMPL_CONVERT(cpp_enum, gl_enum) case name::cpp_enum: return gl_enum;
#define DEF_STATE_ENUM(name, ...) \
enum name { \
PP_FOR_EACH(PP_IMPL_ENUM_VALUE, ##__VA_ARGS__) \
}; \
namespace detail { \
GLenum name ## 2gl(name e) { \
switch(e) { \
__PP_EVAL(PP_FOR_EACH(PP_IMPL_CONVERT, ##__VA_ARGS__)) \
default: \
assert(!"Unknown value"); \
return GL_NONE; \
} \
} \
}
DEF_STATE_ENUM(my_enum,
(foo, GL_FOO),
(bar, GL_BAR)
)
The problem is that __PP_IMPL_CONVERT
uses name
which is not expanded. Passing x
to FOO_BAR
would mean that I'm passing some extra parameter to a functor for PP_FOR_EACH
.
Upvotes: 1
Views: 1251
Reputation: 181319
You need to understand
The preprocessor fully expands the arguments to each function-like macro before substituting them into the macro's expansion, except where they are operands of the #
or ##
preprocessing operators (in which case they are not expanded at all).
After modifying the input preprocessing token sequence by performing a macro expansion, the preprocessor automatically rescans the result for further macro expansions to perform.
In your lead example, then, given
#define FOO_BAR x #define FOO(x) FOO_BAR
and a macro invocation
FOO(2)
, the preprocessor first macro expands the argument 2
, leaving it unchanged, then replaces the macro call with its expansion. Since the expansion does not, in fact, use the argument in the first place, the initial result is
FOO_BAR
The preprocessor then rescans that, recognizes FOO_BAR
as the identifier of an object-like macro, and replaces it with its expansion, yielding
x
, as you observed. This is the normal and expected behavior of a conforming C preprocessor, and to the best of my knowledge, C++ has equivalent specifications for its preprocessor.
Inserting an EXPAND()
macro call does not help, because the problem is not failure to expand macros, but rather the time and context of macro expansion. Ultimately, it should not be all that surprising that when the replacement text of macro FOO(x)
does not use the macro parameter x
, the actual argument associated with that parameter has no effect on the result of the expansion.
I cannot fully address your real-world code on account of the fact that it depends centrally on a macro PP_FOR_EACH()
whose definition you do not provide. Presumably that macro's name conveys the gist, but as you can see, the details matter. However, if you in fact understand how your PP_FOR_EACH
macro actually works, then I bet you could come up with a variant that accepts an additional leading argument, by which you could convey (the same) name
to each expansion.
Alternatively, this is the kind of problem for which X Macros were invented. I see that that alternative has already been raised in comments. You might even be able -- with some care -- to build a solution that uses X macros inside, so as to preserve the top-level interface you now have.
Upvotes: 4