我想创建一个递归宏,它将创建“下一个”类。
示例:
#define PRINTME(indexNum) class m_##(indexNum+1) { }
indexNum + 1
被评估为int
,并且不会连接到类名。
如何在连接之前让编译器评估它?
答案 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__
。)
答案 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 { };
您是否考虑过使用模板?