C++ 扩展C++;要连接的宏中的宏
我必须让CS学生修改一个组号,然后生成一些与该组号相关的东西。我不想让学生修改太多,只想修改定义为C++ 扩展C++;要连接的宏中的宏,c++,macros,concatenation,C++,Macros,Concatenation,我必须让CS学生修改一个组号,然后生成一些与该组号相关的东西。我不想让学生修改太多,只想修改定义为 #define GROUP_NUM 0 但是,我找不到从该宏生成其余部分的方法。 例如: #include <iostream> using namespace std; // string troubles #define STR(x) #x #define XSTR(x) STR(x) // the trouble #define GROUP_NUM 0 #define CL
#define GROUP_NUM 0
但是,我找不到从该宏生成其余部分的方法。
例如:
#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;
}
这里的问题是我不想要组和0之间的空间,因为我需要使用CLASS_NAME从中创建一些类,例如
class CLASS_NAME : public .... { ... }
我试着用
#define CLASS_NAME Group##GROUP_NUM
但是,GROUP_NUM没有得到扩展,而是输出
CLASS_NAME = GroupGROUP_NUM
我找到的唯一解决方案是将这些CLASS_NAME和CLASS_STR定义为宏函数,并将组号作为参数传递(在调用站点上,而不是在另一个宏中!):
上面的XSTR的定义似乎表明可以使用链式宏,所以我不明白为什么它不在这里展开
更新:
helper宏函数的技巧就是解决方案。不过,我想澄清一下解决方案:
#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_NAME,“mystring”),它会被错误地部分扩展为
Group0 * CLASS_NAME_create (const PropertyList &list) { return new Group0 (list); } ...
但是,如果我使用一个包装宏来调用那个包装宏,它就会工作。这里的宏扩展规则是什么?为什么第一个cls被扩展,而第二个cls保留名称?为此使用
BOOST\u PP\u CAT
:
#define CLASS_NAME BOOST_PP_CAT(Group,GROUP_NUM)
为此使用
BOOST\u PP\u CAT
:
#define CLASS_NAME BOOST_PP_CAT(Group,GROUP_NUM)
可行的解决方案是:
#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;
}
可行的解决办法是:
#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;
}
##
操作符仅对令牌起作用。所以需要一个helper宏
试试这个:
#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;
}
#包括
#包括
//麻烦
使用名称空间std;
//麻烦
//串故障
#定义STR(x)#x
#定义XSTR(x)STR(x)
#定义组编号0
#定义类_STR(g)XSTR(组##g)
#定义类别STR2(g)类别STR(g)
int main()
{
cout这个##
操作符只对令牌有效。所以你需要一个helper宏
试试这个:
#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;
}
#包括
#包括
//麻烦
使用名称空间std;
//麻烦
//串故障
#定义STR(x)#x
#定义XSTR(x)STR(x)
#定义组编号0
#定义类_STR(g)XSTR(组##g)
#定义类别STR2(g)类别STR(g)
int main()
{
难道##
操作符只对令牌起作用吗?我想我真的不明白这个操作符是如何工作的。它似乎取决于上下文。我将更新这个问题来解释我所说的上下文……#
操作符只对令牌起作用。我想我真的不明白这个操作符是如何工作的。它似乎取决于上下文我将更新这个问题来解释我所说的上下文…+1,但是,我认为OP想做一些类似于CLASS\u STR(Group,Group\u NUM0)
,和CLASS\u STR(另一个Group,Group\u NUM\u 7)的事情
。您的方法没有任何参数。但是,这与OP的原始示例最接近。它生成两个有用的宏:CLASS_NAME,可以在代码中使用,CLASS_STR,可以在输出中使用。+1用于此。我收回了自己的答案。+1,但是,我认为OP想做类似于CLASS_STR(Group,Group_NUM0)的事情
和类别(另一组,第7组)
。您的方法没有任何参数。但是,这与OP的原始示例最接近。它生成两个有用的宏:CLASS_NAME,可用于代码,CLASS_STR,可用于输出。+1。我收回了我自己的答案。您的解决方案也很好,我不应该直接跳到投票最多的那个(虽然每个都在这里工作)。你能解释一下什么是“令牌”吗?(参考更新的问题)令牌是一个常量表达式。它们不会得到计算。这是不够的。以上面的XSTR(Group##g)为例,据我所知,Group##g不是令牌,否则它会像那样发送给XSTR,并“通过”它本身对STR和helper宏没有帮助。所以Group##g不是一个标记。那么,如果对Group##g进行评估,为什么我不能将它传递给STR呢?你的解决方案也很好,我不应该直接跳到投票最多的一个上(尽管每个都在这里工作)。你能解释一下什么是“标记”吗?(参考更新的问题)令牌是一个常量表达式。它们不会被计算。这是不够的。以上面的XSTR(Group##g)为例,据我所知,Group##g不是令牌,否则它会像那样发送给XSTR,并“通过”因此,Group###g不是一个标记。那么,如果Group##g得到求值,为什么我不能将它传递给STR呢?
#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;
}