我必须让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
问题在于我不希望群组和 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框架,特别是this。 有了这个宏,即
#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会扩展而第二个cls会保留名称?
答案 0 :(得分:3)
可能的解决方案是:
#include <iostream>
using namespace std;
#define CLASS_NUM 0
// String macros
#define XSTR(x) STR(x)
#define STR(x) #x
#define CONCAT(x,y) x##y
// XCONCAT will first process tokens before passing them to CONCAT
#define XCONCAT(x,y) CONCAT(x,y)
// This will generate Group0
#define CLASS_NAME XCONCAT(Group,CLASS_NUM)
// Then this will generate "Group0"
#define CLASS_STR XSTR(CLASS_NAME)
int main()
{
cout << "CLASS_NAME = " << CLASS_STR << endl;
return 0;
}
使用此代码输出为:
CLASS_NAME = Group0
答案 1 :(得分:2)
##
运算符仅适用于令牌。所以你需要一个辅助宏。
试试这个:
#include <ostream>
#include <iostream>
// the trouble
using namespace std;
// the trouble
// string troubles
#define STR(x) #x
#define XSTR(x) STR(x)
#define GROUP_NUM 0
#define CLASS_STR(g) XSTR(Group ## g)
#define CLASS_STR2(g) CLASS_STR(g)
int main()
{
cout << "CLASS_NAME = " << CLASS_STR2(GROUP_NUM) << endl;
return 0;
}
答案 2 :(得分:1)
使用BOOST_PP_CAT
:
#define CLASS_NAME BOOST_PP_CAT(Group,GROUP_NUM)
http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/ref/cat.html