【问题标题】:How to map #define's replacement list containing space(s) to integers (IDs)?如何将包含空格的#define 替换列表映射到整数(ID)?
【发布时间】:2022-08-07 22:13:42
【问题描述】:

#define\ 的不包含空格的替换列表可以映射到整数(ID):

#define ID_double       1
#define ID_float        2
#define ID_long_double  3
#define ID_(x)          ID_##x
#define ID(x)           ID_(x)

#define T               double
T v;
int x = ID(T);          /* 1 */

现在考虑:

#define T               long double

上面的代码不会编译:

<source>:3:25: error: \'ID_long\' undeclared here (not in a function)

问题:有没有办法支持空间?

例如(不知何故):

#define REPLACE_SPACES_TO_UNDERSCORES(x)     ??

#define ID(x)           ID_(REPLACE_SPACES_TO_UNDERSCORES(x))

#define T               long double
T v;
int x = ID(T);          /* 3 */
  • 也许_Generic 可能有用?
  • 使用typedef 语句创建一个不包含空格的别名,即typedef long double long_double;,然后在宏中使用该别名。
  • @RemyLebeau 确实:除了#define T long_double,还需要typedef long double long_double;。谢谢!
  • @RemyLebeau 但是,您不能(?)typedef long double long_double; 通过编译器选项,而您可以通过编译器选项#define T long_double。现在考虑代码是只读的。那么如何在其中插入一个额外的typedef
  • GCC 知道选项-include 添加文件,因为它包含在#include 中。

标签: c c-preprocessor


【解决方案1】:

我在Replace spaces with underscores in a macro? 中的相同想法也可以在这里使用,并且字典的大小会更加逼真。在最后的以下代码中,ID(T) 被替换为3

// dictionary
#define WORD_long     long,
#define WORD_double   double,

// ---------------------------------------------

// the classics
#define COMMA(...)  ,
#define FIRST(a, ...)  a

// apply function f for each argument recursively with tail
#define FOREACHTAIL_1(f,a)      f(a,)
#define FOREACHTAIL_2(f,a,...)  f(a,FOREACHTAIL_1(f,__VA_ARGS__)) 
#define FOREACHTAIL_3(f,a,...)  f(a,FOREACHTAIL_2(f,__VA_ARGS__)) 
#define FOREACHTAIL_4(f,a,...)  f(a,FOREACHTAIL_3(f,__VA_ARGS__)) 
#define FOREACHTAIL_N(_4,_3,_2,_1,N,...)  \
        FOREACHTAIL_##N
#define FOREACHTAIL(f,...) \
        FOREACHTAIL_N(__VA_ARGS__,4,3,2,1)(f,__VA_ARGS__)

// if there are two arguments, expand to true. Otherwise false.
#define IFTWO_N(_0,_1,N,...)     N
#define IFTWO(true, false, ...)  IFTWO_N(__VA_ARGS__, true, false)

// If empty, expand to true, otherwise false.
// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define IFEMPTY(true, false, ...)  IFTWO(true, false, COMMA __VA_ARGS__ ())

// Join arguments with `_`.
#define JOIN_U(a, b)      a##_##b
#define JOIN_TWO_IN(a,b)  IFEMPTY(FIRST, JOIN_U, b)(a, b)
#define JOIN_TWO(a,b)     JOIN_TWO_IN(a,b)
#define JOIN(...)         FOREACHTAIL(JOIN_TWO, __VA_ARGS__)

// Append WORD_ to each argument and join arguments with spaces.
#define WORD_             /* the last one expands to empty */
#define WORDS_TWO(a, b)   WORD_##a b
#define WORDS(...)        FOREACHTAIL(WORDS_TWO, __VA_ARGS__)

#define REPLACE_SPACES_TO_UNDERSCORES(a)  JOIN(WORDS(WORDS(WORDS(WORDS(WORDS(a))))))

// --------------------------------------------

#define ID_double       1
#define ID_float        2
#define ID_long_double  3
#define ID_IN2(x)       ID_##x
#define ID_IN(x)        ID_IN2(x)
#define ID(x)           ID_IN(REPLACE_SPACES_TO_UNDERSCORES(x))

int main() {
    #define T               long double
    T v;
    int x = ID(T);          /* 3 */
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 2021-09-24
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多