English is not my native language; thus I show the code to depict.
#define concat_temp(x, y) x##y
#define concat(x, y) concat_temp(x, y)
#define CHOOSE2nd(a, b, ...) b
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
#define __P_DEF_0 X,
#define __P_DEF_1 X,
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
#define ISDEF(macro) MUXDEF(macro, 1, 0)
#define FOO 1
int main(int argc, char* argv[]) {
ISDEF(FOO) // 1
MUXDEF(FOO, 1, 0) // 1
MUX_MACRO_PROPERTY(__P_DEF_, FOO, 1, 0) // 1
MUX_WITH_COMMA(concat(__P_DEF_, FOO), 1, 0) // 1
CHOOSE2nd(concat(__P_DEF_, FOO) 1, 0) // 0 !!! why?
concat(__P_DEF_, FOO) // X,
CHOOSE2nd(X, 1, 0) // 1
return 0;
}
I am trying to expand the macro ISDEF
manually, but I ran into some trouble.
When the macro is defined as 0 or 1, the ISDEF
will be expanded to 1.
However, there are more args that need to be expanded in MUX_WITH_COMMA(concat(__P_DEF_, FOO), 1, 0)
which are MUX_WITH_COMMA
and concat
;
I think the former will be expanded first in that MUX_WITH_COMMA(X,, 1, 0)
is incorrect.
In the line which I expand manually CHOOSE2nd(concat(__P_DEF_, FOO) 1, 0)
the first expansion is CHOOSE2nd
and the result is 0;
but in the original expression the order should be
MUX_WITH_COMMA
->CHOOSE2nd
concat(__P_DEF_, FOO)
->X,
CHOOSE2nd(X, 1, 0)
->1
I guess that the preprocessor will expand the args in the brackets after processing the other part just once, and then repeat this process until no macro can be expanded. Is it the right explanation?
Another likely possible order is that the preprocessor will prioritize the args in bracket, like this:
ISDEF(1) // 1
MUXDEF(1, 1, 0) // 1
MUX_MACRO_PROPERTY(__P_DEF_, 1, 1, 0) // 1
MUX_WITH_COMMA(concat(__P_DEF_, 1), 1, 0) // 1
CHOOSE2nd(concat(__P_DEF_, 1) 1, 0) // 0
CHOOSE2nd(X, 1, 0) // 1
CodePudding user response:
Although I have still not found a reliable reference to explain it, it seems that the expanded arg which contains comma will not be counted as two args. Like this:
#define FOO(x) x
#define A a,a
int main() {
FOO(A) // a,a
}
Thus the correct order in the question is that:
ISDEF(1) // 1
MUXDEF(1, 1, 0) // 1
MUX_MACRO_PROPERTY(__P_DEF_, 1, 1, 0) // 1
MUX_WITH_COMMA(concat(__P_DEF_, 1), 1, 0) // 1
//MUX_WITH_COMMA(X,, 1, 0) // compile error
//But if the `X,` is expand by a macro it will not be count as two args.
CHOOSE2nd(X, 1, 0) // 1
CodePudding user response:
Expand
ISDEF(FOO)
Expand
FOO
->
1
->
MUXDEF(1, 1, 0)
Expand
MUXDEF(macro, X, Y)
->
MUX_MACRO_PROPERTY(__P_DEF_, 1, 1, 0)
Expand
MUX_MACRO_PROPERTY(p, macro, a, b)
->
MUX_WITH_COMMA(concat(__P_DEF_, 1), 1, 0)
Expand
concat(x, y)
->
concat_temp(__P_DEF_, 1)
Expand
concat_temp(__P_DEF_, 1)
->
__P_DEF_##1
Apply
##
->
__P_DEF_1
Expand
__P_DEF_1
->
X,
->
MUX_WITH_COMMA(X, 1, 0)
Expand
MUX_WITH_COMMA(contain_comma, a, b)
->
CHOOSE2nd(X, 1, 0)
Expand
CHOOSE2nd(a, b, ...)
->
1
Expand
ISDEF(BAR)
->
MUXDEF(BAR, 1, 0)
Expand
MUXDEF(macro, X, Y)
->
MUX_MACRO_PROPERTY(__P_DEF_, BAR, 1, 0)
Expand
MUX_MACRO_PROPERTY(p, macro, a, b)
->
MUX_WITH_COMMA(concat(__P_DEF_, BAR), 1, 0)
Expand
concat(x, y)
->
concat_temp(__P_DEF_, BAR)
Expand
concat_temp(__P_DEF_, BAR)
->
__P_DEF_##BAR
Apply
##
->
__P_DEF_BAR
->
MUX_WITH_COMMA(__P_DEF_BAR, 1, 0)
Expand
MUX_WITH_COMMA(contain_comma, a, b)
->
CHOOSE2nd(__P_DEF_BAR 1, 0)
Expand
CHOOSE2nd(a, b, ...)
->
0