在将宏传递给另一个宏而不是直接传递事物时,会出现多余的“空”自变量

问题描述 投票:1回答:1

问题(简洁)

(下面是完整的最小代码),以某种方式,当我将一个简单的参数列表传递给宏时,一切都很好。

#pragma message STRINGIZE( ( DUMMY_WRAPPER (initial_argument, arg2, arg3)))

在上面的编译过程中,我看到了编译器/预处理器的预期输出:

#pragma message: ( initial_argument { {initial_argument, arg2} , {initial_argument, arg3} }; 2)

但是,当我尝试使用参数定义宏并将that传递到DUMMY_WRAPPER时,我得到了一个“额外的”空参数。示例:

#define ARGS initial_argument, arg2, arg3
#pragma message STRINGIZE( ( DUMMY_WRAPPER (ARGS) ))

编译器输出(与正确的输出比较:):]

#pragma message: ( initial_argument { {initial_argument, arg2} , {initial_argument, arg3} , {initial_argument, } }; 3 )

如何摆脱这个多余的论点?

完整代码(带说明)

Nota Bene:我完全承认这可能是非常糟糕的宏滥用,并且有很多更好的方法可以使用C ++进行元编程,但是我只是想尽快使它起作用。

我使用GCC / G ++进行编译。

这里是工作代码+编译器输出,可让您轻松地在线测试/试验:https://godbolt.org/z/wGFbrK

#define COMMA() ,

// routines for stringizing macros, similar to BOOST_PP_STRINGIZE
#define STR1(x) #x
#define STRINGIZE(x) STR1(x)

// routine & subroutines for argument counting
#define NARG(...)                                                        \
  NARG_(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
#define ARG_N(_1,_2,_3,_4,_5, N, ... ) N
#define NARG_(...) ARG_N(__VA_ARGS__)

// routines for "looped" macro expansion, for processing lists of macro arguments
#define LOOP_1(M, C, D, x) M(C, x)
#define LOOP_2(M, C, D, x, ...) M(C, x) D()                              \
  LOOP_1(M, C, D, __VA_ARGS__)
#define LOOP_3(M, C, D, x, ...) M(C, x) D()                              \
  LOOP_2(M, C, D, __VA_ARGS__)
#define LOOP_4(M, C, D, x, ...) M(C, x) D()                              \
  LOOP_3(M, C, D, __VA_ARGS__)
#define LOOP_5(M, C, D, x, ...) M(C, x) D()                              \
  LOOP_4(M, C, D, __VA_ARGS__)

// routine for concatenating things, used here to expand loop routine names, i.e. LOOP_ + 3 => LOOP_3
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a##__VA_ARGS__

// **** TOP-LEVEL ****
// (code using above routines to demonstrate the problem)

// lists the first argument, i.e. C in the loop, and some other argument
#define LIST_FIELD(arg1, a, ... ) {arg1, a}

#define DUMMY_WRAPPER(arg1, ...) DUMMY( arg1, __VA_ARGS__)

#define DUMMY( arg1, ...)                                                   \
    DUMMY_2(arg1, NARG(__VA_ARGS__), __VA_ARGS__)

#define DUMMY_2( arg1, field_count, ...)                                    \
    DUMMY_3(arg1, CAT(LOOP_, field_count), __VA_ARGS__)                     \
    field_count

#define DUMMY_3( arg1, loop, ...)                                           \
    arg1 {                                                                  \
        loop(LIST_FIELD, arg1, COMMA, __VA_ARGS__)   \
    };

#pragma message STRINGIZE( ( DUMMY_WRAPPER (initial_argument, arg2, arg3)))
#define ARGS initial_argument, arg2, arg3
#pragma message STRINGIZE( ( DUMMY_WRAPPER (ARGS) ))

(某些)可能相关的研究(不确定)

https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/

虽然不知道这是否可以在这里说明问题,但直觉上我认为不是...

问题(简洁)(遵循最少的代码),以某种方式,当我将简单的参数列表传递给宏时,一切都很好。 #pragma message STRINGIZE((DUMMY_WRAPPER(initial_argument,arg2,...

c++ preprocessor
1个回答
1
投票

当编译器看到此内容时:DUMMY_WRAPPER (ARGS)

© www.soinside.com 2019 - 2024. All rights reserved.