VC ++ preprocessor vs GCC

In short, the gcc and vC ++ preprocessors have different outputs with the same input. Variable macros in vC ++ do not seem to perform "argument matching" (if that is the correct term) if passed to other macros. For example:

#define MACRO(a, ...) head:a, tail:MACRO_OTHER(__VA_ARGS__) #define MACRO_OTHER(a, ...) head:a, tail:__VA_ARGS__ 

FROM

 MACRO(1, 2, 3, 4, 5) 

Gcc output:

 head:1, tail:head:2, tail:3,4,5 

vC ++ output:

 head:1, tail:head:2,3,4,5, tail: 

Apparently a in MACRO_OTHER has 2,3,4,5 with an empty section of variational arguments. With that in mind, is there a way to create an alternative to vC ++ for the next macro (which works fine with gcc)

 #define VA_TYPES_WITH_ARGS(...) __VA_TYPES_WITH_ARGS(VA_NUM_ARGS(__VA_ARGS__),##__VA_ARGS__) #define __VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS(n,##__VA_ARGS__) #define _VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS_##n(__VA_ARGS__) #define _VA_TYPES_WITH_ARGS_0() #define _VA_TYPES_WITH_ARGS_1(type ) type _arg1 #define _VA_TYPES_WITH_ARGS_2(type, ...) type _arg2, _VA_TYPES_WITH_ARGS_1(__VA_ARGS__) #define _VA_TYPES_WITH_ARGS_3(type, ...) type _arg3, _VA_TYPES_WITH_ARGS_2(__VA_ARGS__) // etc 

It basically adds _argK for each argument.

Example:

 VA_TYPES_WITH_ARGS(int, bool, float) 

will expand to

 int _arg3, bool _arg2, float _arg1 

Any help would be greatly appreciated.


Preprocessor related questions:

The difference between gcc and Microsoft preprocessor

Unexpected behavior of the GCC and VC ++ preprocessor

+7
c ++ gcc macros c-preprocessor visual-c ++
source share
2 answers

You can do this in a smart cross-compiler (and take many more arguments without extra work to load) with Boost, which I can tell you to spend so much time on headers, has many workarounds for issues like:

 #define VA_TYPES_WITH_ARGS(...) \ BOOST_PP_ENUM( \ BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \ VA_TYPES_WITH_ARGS_MACRO, \ BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \ ) #define VA_TYPES_WITH_ARGS_MACRO(z, n, data) \ BOOST_PP_TUPLE_ELEM(n, data) BOOST_PP_CAT( \ _arg, \ BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(data), n) \ ) VA_TYPES_WITH_ARGS(int, bool, float) //int _arg3 , bool _arg2 , float _arg1 

The first macro enumerates ( ENUM ) by variable arguments, invoking the second for each and adding a comma. It forms a tuple from the variation data to obtain a second macro.

The second form, in which the element ( TUPLE_ELEM ) followed by _arg , is combined ( CAT ) with size - n ( SUB ), where size is the number of elements in the variation data (this macro is like a tuple) ( TUPLE_SIZE ).

See how it works.

+3
source share

Standalone approach that works for VC ++, and breaks with GCC:

 #define EXPAND(...) __VA_ARGS__ #define LPAREN ( #define RPAREN ) 

Now instead of using a macro like x(__VA_ARGS__) , use it like this: EXPAND(x LPAREN __VA_ARGS__ RPAREN) .

This forces the VC ++ preprocessor to scan the arguments later than usual.

You should be able to combine the two forms to put the bits specific to the compiler in one place.

Note that there cannot be a standard C ++ answer: you rely on x() as a macro call with no arguments. This is not how the preprocessor works in standard C ++: if x is a variable macro, x() calls the macro with one argument, and this single argument is empty. In addition, you rely on the ability to omit variable arguments: standard C ++ also does not allow this. If the macro is defined as #define FOO(x,...) , calling it as FOO(1) is not valid. Since there cannot be a standard approach, I hope it will not be a problem for you that the various approaches will necessarily be specific to the compiler.

+3
source share

All Articles