宏增加值然后连接

时间:2012-07-30 08:02:58

标签: c++ macros concatenation

我想创建一个递归宏,它将创建“下一个”类。

示例:

#define PRINTME(indexNum) class m_##(indexNum+1) { }

indexNum + 1被评估为int,并且不会连接到类名。

如何在连接之前让编译器评估它?

3 个答案:

答案 0 :(得分:5)

如果要在每次调用PRINTME时生成唯一的类名,则以下是一种方式:

#define CONCATE1(X,Y) X##Y
#define CONCATE(X,Y)  CONCATE1(X,Y)

#define PRINTME class CONCATE(m_,__COUNTER__) {}

__COUNTER__是gcc的扩展,我不确定它是否存在于其他编译器中。每次调用此宏时,都保证编译器将添加1 (在这种情况下,您无法有效使用__LINE____FILE__。)

Demo

答案 1 :(得分:4)

简单的答案是,你做不到。预处理器通常处理文本和令牌;唯一的位置算术是在#if#elif指令中执行的。

此外,宏扩展不是递归的。在扩展期间,正在扩展的宏被禁用,并且无法进一步替换。

答案 2 :(得分:2)

根据你的动机和忍受丑陋代码的能力,它是可行的。首先定义增量宏:

#define PLUS_ONE(x) PLUS_ONE_##x

#define PLUS_ONE_0 1
#define PLUS_ONE_1 2
#define PLUS_ONE_2 3
#define PLUS_ONE_3 4
#define PLUS_ONE_4 5
#define PLUS_ONE_5 6
#define PLUS_ONE_7 8
#define PLUS_ONE_8 9
#define PLUS_ONE_9 10
// and so on...

您不能在连接操作中使用PLUS_ONE(x),因为预处理器不会扩展它。但是有一种方法 - 你可以滥用预处理器扩展可变参数的事实。

// pass to variadic macro to expand an argument
#define PRINTME(indexNum)       PRINTME_PRIMITIVE(PLUS_ONE(indexNum))
// do concatenation
#define PRINTME_PRIMITIVE(...)  class m_ ## __VA_ARGS__ { }

完成!

PRINTME(1); // expands to class m_2 { };

您是否考虑过使用模板?