我必须让 CS 学生修改一个组号,然后生成一些与该号码相关的东西。我不希望学生修改太多,但只修改某处定义为的一个组号
#define GROUP_NUM 0
但是,我找不到从该 MACRO 生成其余部分的方法。例如:
#include <iostream>
using namespace std;
// string troubles
#define STR(x) #x
#define XSTR(x) STR(x)
// the trouble
#define GROUP_NUM 0
#define CLASS_NAME Group GROUP_NUM
#define CLASS_STR XSTR(CLASS_NAME)
int main()
{
cout << "CLASS_NAME = " << CLASS_STR << endl;
return 0;
}
悲伤地输出
CLASS_NAME = Group 0
这里的问题是我不希望Group和0之间有那个空间,因为我需要使用 CLASS_NAME 来创建一些类,例如
class CLASS_NAME : public .... { ... }
我试着用
#define CLASS_NAME Group##GROUP_NUM
但随后 GROUP_NUM 没有得到扩展,它输出
CLASS_NAME = GroupGROUP_NUM
我发现的唯一解决方案是将这些 CLASS_NAME 和 CLASS_STR 定义为宏函数,将组号作为参数传递(在调用站点上,而不是在另一个宏中!):
// the trouble
#define GROUP_NUM 0
#define CLASS_NAME(g) Group ## g
#define CLASS_STR(g) XSTR(CLASS_NAME(g))
int main()
{
cout << "CLASS_NAME = " << CLASS_STR(GROUP_NUM) << endl;
return 0;
}
有更好的解决方案吗?为什么以下内容不展开?
#define CLASS_STR XSTR(CLASS_NAME(GROUP_NUM))
上面XSTR的定义似乎表明可以使用链式宏,所以我不明白为什么它没有在这里展开。
更新:辅助宏函数的诀窍是解决方案。但是我想澄清解决方案:
- 宏扩展技巧如何工作?它是直接完全扩展还是只进行一轮扩展?(即如果我有叠瓦宏,这是否意味着我需要不止一层辅助函数?)
- ## 的扩展对我来说仍然有些神秘
我的全部问题是涉及nori 框架,尤其是这个。有了那个宏,即
#define NORI_REGISTER_CLASS(cls, name) \
cls *cls ##_create(const PropertyList &list) { \
return new cls(list); \
} \
static struct cls ##_{ \
cls ##_() { \
NoriObjectFactory::registerClass(name, cls ##_create); \
} \
} cls ##__;
如果我使用 NORI_REGISTER_CLASS(CLASS_NAME, "mystring"),它会错误地部分扩展为
Group0 * CLASS_NAME_create (const PropertyList &list) { return new Group0 (list); } ...
但是,如果我使用一个包装宏来调用那个,它就可以工作。这里的宏扩展规则是什么?为什么第一个 cls 得到扩展而第二个保留名称?