簡體   English   中英

C ++宏在要連接的宏中的擴展

[英]Expansion of C++ macro within macro to be concatenated

我必須讓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

這里的麻煩是我不希望Group0之間存在該空間,因為我需要使用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的定義似乎表明一個人可以使用鏈接的宏,因此我不明白為什么它在這里沒有得到擴展。

更新 :解決方案是助手宏功能的竅門。 但是我想澄清解決方案:

  1. 宏擴展技巧如何工作? 它是直接完全擴展還是僅進行一輪擴展? (即,如果我有宏指令,那是否意味着我需要一層以上的輔助函數?)
  2. ##的擴展對我來說仍然有些神秘

我的全部問題都涉及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擴展而第二個cls保留名稱?

可能的解決方案是:

#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

##運算符僅適用於令牌。 因此,您需要一個輔助宏。

嘗試這個:

#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;
}

為此使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM