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).
What exactly I am trying to accomplish
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.
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.
Related
How does one prevent simple macro substitution?
e.g.
#define number 0x10
int number = 0x5;
I know this can be done for function-style macros, like min and max, by surrounding the macro with parentheses (thus, separating it from the adjacent parentheses that would've been used for the args):
#define max(...)
void (max)();
My current method is to push the macro value, undefine it, use it, then pop the original value.
You can't prevent macro substitution.
That's one of the reasons why macros are usually all caps:
#define NUMBER 0x10
int number = 0x5; // no problem here.
Even this can be done of course:
int number = NUMBER; // even this can be done of course
I would advise using const variables when you want to define constants instead of using macros. And to avoid name collisions maybe just add some prefix or suffix to the name or capitalize the name.
In c++ you can even use constexpr.
There is no standard way for this but you can do the following:
#define number 0x10
#pragma push_macro("number")
#undef number
int number = 0x5;
#pragma pop_macro("number")
The #undef directive undefines a constant or preprocessor macro defined previously using #define.
Refer: https://www.cprogramming.com/reference/preprocessor/undef.html
So, basically I'm trying to implement a macro to count the number of arguments in VA_ARGS.
For the sake of simplicity it only works up to 3 parameters. The problem is that when the macro is used with less than 3 parameters, it doesn't work, and triggers the "expected an expression" error.
#define EXPAND( x ) x
#define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, PP_RSEQ_N()))
#define PP_ARG_N(_1, _2, _3, N,...) N
#define PP_RSEQ_N() 3,2,1,0
void main()
{
printf("\nTEST PP_NARG: %i", PP_NARG()); //Doesn't work (in this case it shouldn't work, so it's correct)
printf("\nTEST PP_NARG: %i", PP_NARG(0)); //Doesn't work
printf("\nTEST PP_NARG: %i", PP_NARG(0,0)); //Doesn't work
printf("\nTEST PP_NARG: %i", PP_NARG(0,0,0)); //Works
}
Keeping just the line that works it compiles correctly and prints "TEST PP_NARG: 3".
I believe the problem might be that PP_RSEQ_N() is only expanding to "3", instead of "3,2,1,0" for some reason, since even if PP_RSEQ_N() is defined as this
#define PP_RSEQ_N() 10,9,8,7,6,5,4,3,2,1,0
it still doesn't work with less than 3 parameters.
Im using the MSVC compiler and it may be the cause of the problem, since it doesn't behave very well with macros, as seen here: MSVC doesn't expand __VA_ARGS__ correctly
In your implementation PP_RSEQ_N() is an argument to PP_ARG_N. As an argument, it is only expanded in the argument substitution phase of preprocessing, but that only happens just prior to replacing the argument in its replacement list (so long as, in the replacement list, it's not being stringified and is not participating in a paste).
Since PP_ARG_N only has its fourth argument N in its replacement list, PP_RSEQ_N() will only expand if you happen to pass three arguments in. (There is a second scan during the rescan and replacement phase, which applies after argument substitution... but that has no effect here as PP_RSEQ_N() is mentioned in a call).
Get rid of this macro and just put it in the PP_NARG like this:
#define EXPAND( x ) x
#define PP_NARG(...) EXPAND(PP_ARG_N(__VA_ARGS__, 3,2,1,0))
#define PP_ARG_N(_1, _2, _3, N,...) N
...and things "work" fine:
PP_NARG() expands to 1
PP_NARG(x) expands to 1
PP_NARG(x,y) expands to 2
Note, however, that PP_NARG() doesn't give you 0. Arguably that's actually correct; to the preprocessor, this is not passing zero arguments. It's passing one argument that is just empty. It's the same thing as #define X(A) OPEN A CLOSE/X() yielding OPEN CLOSE. If for some reason you want this to expand to 0, there may be some finagling to get that to happen, but for this answer I'm only focusing on getting you over this one hump.
A PP_ARG_N() implementation which can also distinguish between invocation with and without parameter can be found here (kudos to Scott Morrison). Response for your little program:
TEST PP_NARG: 0
TEST PP_NARG: 1
TEST PP_NARG: 2
TEST PP_NARG: 3
I'm trying to conditionally expand a macro to either "( a" or "b )", but the naive way of doing so doesn't work on either of the compilers I'm using (Microsoft C/C++ and the NDK compiler). Example:
// This works on both compilers, expands to ( a ) as expected
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a BOOST_PP_RPAREN(), b)
// MSVC: syntax error/unexpected end of file in macro expansion
// NDK: unterminated argument list
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a, b)
// Desired expansion: ( a
// MSVC expansion: ( a, b )
// NDK: error: macro "BOOST_PP_IIF" requires 3 arguments, but only 2 given
#define PARENS_AND_SUCH BOOST_PP_IF(1, BOOST_PP_LPAREN() a, b BOOST_PP_RPAREN())
What am I doing wrong?
You could force the order of evaluation to conform to the expected one by abstracting out the branches of the IF to subdefinitions, and delay their expansion until the conditional returns a branch:
#define PARENS_AND_SUCH BOOST_PP_CAT(PAS_, BOOST_PP_IF(1, THEN, ELSE))
#define PAS_THEN BOOST_PP_LPAREN() a
#define PAS_ELSE b BOOST_PP_RPAREN()
Since THEN and ELSE aren't complete names, the branches will not be expanded before the IF is expanded; when it returns, the value is combined with PAS_ to form a new valid definition and will expand at that time.
You could also parameterise the THEN and ELSE macros and make this technique more general (and IMO more elegant): passing parameters to an incomplete name essentially forms a thunk, and works pretty much the same way (the incomplete function-like macro name will be passed around plus parameter list until it's completed).
If have encountered this claim multiple times and can't figure out what it is supposed to mean. Since the resulting code is compiled using a regular C compiler it will end up being type checked just as much (or little) as any other code.
So why are macros not type safe? It seems to be one of the major reasons why they should be considered evil.
Consider the typical "max" macro, versus function:
#define MAX(a,b) a < b ? a : b
int max(int a, int b) {return a < b ? a : b;}
Here's what people mean when they say the macro is not type-safe in the way the function is:
If a caller of the function writes
char *foo = max("abc","def");
the compiler will warn.
Whereas, if a caller of the macro writes:
char *foo = MAX("abc", "def");
the preprocessor will replace that with:
char *foo = "abc" < "def" ? "abc" : "def";
which will compile with no problems, but almost certainly not give the result you wanted.
Additionally of course the side effects are different, consider the function case:
int x = 1, y = 2;
int a = max(x++,y++);
the max() function will operate on the original values of x and y and the post-increments will take effect after the function returns.
In the macro case:
int x = 1, y = 2;
int b = MAX(x++,y++);
that second line is preprocessed to give:
int b = x++ < y++ ? x++ : y++;
Again, no compiler warnings or errors but will not be the behaviour you expected.
Macros aren't type safe because they don't understand types.
You can't tell a macro to only take integers. The preprocessor recognises a macro usage and it replaces one sequence of tokens (the macro with its arguments) with another set of tokens. This is a powerful facility if used correctly, but it's easy to use incorrectly.
With a function you can define a function void f(int, int) and the compiler will flag if you try to use the return value of f or pass it strings.
With a macro - no chance. The only checks that get made are it is given the correct number of arguments. then it replaces the tokens appropriately and passes onto the compiler.
#define F(A, B)
will allow you to call F(1, 2), or F("A", 2) or F(1, (2, 3, 4)) or ...
You might get an error from the compiler, or you might not, if something within the macro requires some sort of type safety. But that's not down to the preprocessor.
You can get some very odd results when passing strings to macros that expect numbers, as the chances are you'll end up using string addresses as numbers without a squeak from the compiler.
Well they're not directly type-safe... I suppose in certain scenarios/usages you could argue they can be indirectly (i.e. resulting code) type-safe. But you could certainly create a macro intended for integers and pass it strings... the pre-processor handling the macros certainly doesn't care. The compiler may choke on it, depending on usage...
Since macros are handled by the preprocessor, and the preprocessor doesn't understand types, it will happily accept variables that are of the wrong type.
This is usually only a concern for function-like macros, and any type errors will often be caught by the compiler even if the preprocessor doesn't, but this isn't guaranteed.
An example
In the Windows API, if you wanted to show a balloon tip on an edit control, you'd use Edit_ShowBalloonTip. Edit_ShowBalloonTip is defined as taking two parameters: the handle to the edit control and a pointer to an EDITBALLOONTIP structure. However, Edit_ShowBalloonTip(hwnd, peditballoontip); is actually a macro that evaluates to
SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)(peditballoontip));
Since configuring controls is generally done by sending messages to them, Edit_ShowBalloonTip has to do a typecast in its implementation, but since it's a macro rather than an inline function, it can't do any type checking in its peditballoontip parameter.
A digression
Interestingly enough, sometimes C++ inline functions are a bit too type-safe. Consider the standard C MAX macro
#define MAX(a, b) ((a) > (b) ? (a) : (b))
and its C++ inline version
template<typename T>
inline T max(T a, T b) { return a > b ? a : b; }
MAX(1, 2u) will work as expected, but max(1, 2u) will not. (Since 1 and 2u are different types, max can't be instantiated on both of them.)
This isn't really an argument for using macros in most cases (they're still evil), but it's an interesting result of C and C++'s type safety.
There are situations where macros are even less type-safe than functions. E.g.
void printlog(int iter, double obj)
{
printf("%.3f at iteration %d\n", obj, iteration);
}
Calling this with the arguments reversed will cause truncation and erroneous results, but nothing dangerous. By contrast,
#define PRINTLOG(iter, obj) printf("%.3f at iteration %d\n", obj, iter)
causes undefined behavior. To be fair, GCC warns about the latter, but not about the former, but that's because it knows printf -- for other varargs functions, the results are potentially disastrous.
When the macro runs, it just does a text match through your source files. This is before any compilation, so it is not aware of the datatypes of anything it changes.
Macros aren't type safe, because they were never meant to be type safe.
The compiler does the type checking after macros had been expanded.
Macros and there expansion are meant as a helper to the ("lazy") author (in the sense of writer/reader) of C source code. That's all.
At: http://www.learncpp.com/cpp-tutorial/110-a-first-look-at-the-preprocessor/
It mentions a directive called "Macro defines". What do we mean when we say "Macro"?
Thanks.
A macro is a preprocessor directive that defines a name that is to be replaced (or removed) by the preprocessor right before compilation.
Example:
#define MY_MACRO1 somevalue
#define MY_MACRO2
#define SUM(a, b) (a + b)
then if anywhere in the code (except in the string literals) there is a mention of MY_MACRO1 or MY_MACRO2 the preprocessor replaces this with whatever comes after the name in the #define line.
There can also be macros with parameters (like the SUM). In that case the preprocessor recognizes the arguments, example:
int x = 1, y = 2;
int z = SUM(x, y);
preprocessor replaces like this:
int x = 1, y = 2;
int z = (x + y);
only after this replacement the compiler gets to compile the resulting code.
A macro is a code fragment that gets substituted into your program by the preprocessor (before compilation proper begins). This may be a function-like block, or it may be a constant value.
A warning when using a function-like macro. Consider the following code:
#define foo(x) x*x
If you call foo(3), it will become (and be compiled as) 3*3 (=9). If, instead, you call foo(2+3), it will become 2+3*2+3, (=2+6+3=11), which is not what you want. Also, since the code is substituted in place, foo(bar++) becomes bar++ * bar++, incrementing bar twice.
Macros are powerful tools, but it can be easy to shoot yourself in the foot while trying to do something fancy with them.
"Macro defines" merely indicate how they are specified (with #define directives), while "Macro" is the function or expression that is defined.
There is little difference between them aside from semantics, however.