【问题标题】:Creating list of stringized macro arguments with variadics and late expansions使用可变参数和后期扩展创建字符串化宏参数列表
【发布时间】:2014-01-19 05:29:03
【问题描述】:

我有以下问题 - 给定可变数量的宏参数 argX 以创建字符串化参数列表#argX

例子:

LIST(A, B) -> "A", "B"
LIST(A, B, C) -> "A", "B", "C"

我正在使用 Boost,因此对于每个数量的参数使用辅助宏并将 LIST(...) 分派到适当的 LIST_n(arg1, ... argn) 来实现上述宏并不难。

当 LIST 的输入本身是宏时,问题就开始了。在这种情况下(如果我使用 ... 和 __VA_ARGS__),宏在被字符串化之前会被扩展,给出:

#define A 10
LIST(A, B) -> "10", "B"

我希望它可以与 Windows 标头中定义的宏一起使用,并且大多数值都是宏(MB_OK、AF_INET、...),所以我得到的只是一个字符串化数字列表。

不使用 __VA_ARGS__ 时一切正常:

#define A 10
#define LIST_1(arg0) #arg0
LIST_1(A) -> "A"

我尝试了几个将 __VA_ARGS__ 的扩展推迟到稍后时间的宏(例如,直到 LIST_1,它没有可变参数),但没有任何效果。

这甚至可以使用 C 预处理器来实现吗?

【问题讨论】:

    标签: c macros stringification variadic-macros boost-preprocessor


    【解决方案1】:

    很抱歉,现在可以在 msvc 上执行此操作。由于预处理器中的经典错误(参见herehere),他们将__VA_ARGS__ 视为单个参数。要将其分解为单独的参数,需要应用另一个扫描,然后该扫描也会扩展宏。在 C99 预处理器上,您可以使用空占位符来禁止 __VA_ARGS__ 的扩展:

    /* This counts the number of args */
    #define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
    #define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
    
    /* This will let macros expand before concating them */
    #define PRIMITIVE_CAT(x, y) x ## y
    #define CAT(x, y) PRIMITIVE_CAT(x, y)
    
    /* p is an empty placeholder used to inhibit the expansion of __VA_ARGS__ */
    #define STRINGIZE_ALL(p, ...) FIRST(NARGS(__VA_ARGS__), PRIMITIVE_STRINGIZE_ALL(p ## __VA_ARGS__,~,~,~,~,~,~,~,~))
    #define PRIMITIVE_STRINGIZE_ALL(x1, x2, x3, x4, x5, x6, x7, x8, ...)  #x1, #x2, #x3, #x4, #x5, #x6, #x7, #x8
    
    /* Retrieve the first n arguments from __VA_ARGS__ */
    #define FIRST(n, ...) CAT(FIRST_, n)(__VA_ARGS__,~,~,~,~,~,~,~,~)
    #define FIRST_1(x1, ...) x1
    #define FIRST_2(x1, x2, ...) x1, x2
    #define FIRST_3(x1, x2, x3, ...) x1, x2, x3
    #define FIRST_4(x1, x2, x3, x4, ...) x1, x2, x3, x4
    #define FIRST_5(x1, x2, x3, x4, x5, ...) x1, x2, x3, x4, x5
    #define FIRST_6(x1, x2, x3, x4, x5, x6, ...) x1, x2, x3, x4, x5, x6
    #define FIRST_7(x1, x2, x3, x4, x5, x6, x7, ...) x1, x2, x3, x4, x5, x6, x7
    #define FIRST_8(x1, x2, x3, x4, x5, x6, x7, x8, ...) x1, x2, x3, x4, x5, x6, x7, x8
    
    #define A 10
    STRINGIZE_ALL(, A, B)
    

    这将适用于 gcc 和 clang 3.4 或更高版本的多达 8 个参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 2020-07-12
      • 2014-09-01
      • 2012-01-25
      相关资源
      最近更新 更多