Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 扩展C++;要连接的宏中的宏_C++_Macros_Concatenation - Fatal编程技术网

C++ 扩展C++;要连接的宏中的宏

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

我必须让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 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宏函数的技巧就是解决方案。不过,我想澄清一下解决方案:

  • 宏扩展技巧是如何工作的?它是直接完全扩张还是只进行一轮扩张?(即,如果我有叠瓦宏,这是否意味着我需要不止一层的辅助函数?)
  • ##的扩展对我来说仍然有点神秘
  • 我的全部问题涉及到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_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;
    }