MSVC uses the traditional preprocessor by default.
When this preprocessor is executed with the /EP
command line switch and it invokes the following concatenating macro CONCAT(aa,bb,cc)
, it generates the correct output:
aabbcc
... but it also generates this undesirable warning:
Warning C4003: not enough arguments for function-like macro invocation 'CONCAT'
See the online simulation here.
The CONCAT()
macro is defined below ( it can be invoked with an arbitrary number of arguments ):
#if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL
#pragma warning( push )
#pragma warning( disable : 4003 )
#define CONCAT_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) A##B##C##D##E##F##G##H##I##J##K##L##M##N##O##P##Q##R##S##T##U##V##W##X##Y##Z
#define CONCAT(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z) CONCAT_(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)
#pragma warning( pop )
#else
#define CONCAT_EVAL1(...) __VA_ARGS__
#define CONCAT_EVAL2(...) CONCAT_EVAL1(CONCAT_EVAL1(CONCAT_EVAL1(CONCAT_EVAL1(__VA_ARGS__))))
#define CONCAT_EVAL3(...) CONCAT_EVAL2(CONCAT_EVAL2(CONCAT_EVAL2(CONCAT_EVAL2(__VA_ARGS__))))
#define CONCAT_EVAL4(...) CONCAT_EVAL3(CONCAT_EVAL3(CONCAT_EVAL3(CONCAT_EVAL3(__VA_ARGS__))))
#define CONCAT_EVAL5(...) CONCAT_EVAL4(CONCAT_EVAL4(CONCAT_EVAL4(CONCAT_EVAL4(__VA_ARGS__))))
#define CONCAT_EMPTY()
#define CONCAT_TUPLE_AT_1(a,b,...) b
#define CONCAT_CHECK(...) CONCAT_TUPLE_AT_1(__VA_ARGS__)
#define CONCAT_PROBE(...) ,CONCAT_END,
#define CONCAT_IND() CONCAT_
#define CONCAT_(x,a,...) CONCAT_CHECK(CONCAT_PROBE a,CONCAT_NEXT)(x,a,__VA_ARGS__)
#define CONCAT_NEXT(x,a,...) CONCAT_IND CONCAT_EMPTY()()(x##a,__VA_ARGS__)
#define CONCAT_END(x,a,...) x
#define CONCAT(...) CONCAT_EVAL5(CONCAT_(,__VA_ARGS__,()))
#endif
Of course, when the standard conforming preprocessor is invoked with the /Zc:preprocessor
command line switch, then the condition #if !defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL
fails and the offending code is not expanded and the warning C4003 is not generated.
Notice, that if the /EP
switch is not in effect, then the warning C4003 can be disabled for the macro invocation with #pragma warning( disable : 4003 )
.
See this online simulation.
...but as soon as you add the /EP
switch to the compiler's options, this warning reappears!
QUESTION: How to disable this warning in the traditional preprocessor for just this concatenating macro when the /EP
switch is in effect ...or how to alter this macro so it does not generate that warning with the traditional preprocessor and the /EP
switch ?
NOTE:
Please do not suggest using the global switch /wd"4003"
to disable this warning everywhere, because this warning is needed to check other macros in other code.