2014-10-31 82 views
0

我有#define d預處理器常量叫做CurrentClass
Method讀取此常量以構建當前類的方法聲明。使用#define from宏

#define CurrentClass Foo 
#define Method(x) \ 
    CurrentClass ## _ ## x 

void Method(bar)() { 

} 

預處理產生以下結果:

void CurrentClass_bar() { 

} 

顯然,這裏CurrentClass_bar應該是Foo_bar
另一方面,以下產生正確的結果。

#define Method(class, x) \ 
    class ## _ ## x 

void Method(Foo, bar)() { 

} 

出於某種原因,Method不能連接不斷CurrentClass別的東西。單獨產生CurrentClass字符串。

任何想法這裏發生了什麼?

+0

這只是預處理器的工作方式。嘗試'#define Method(x)_Method(CurrentClass,x)/ #define _Method(a,b)a ## _ ## b'。 – Kevin 2014-10-31 23:04:15

+0

@Kevin Nope,同樣的結果。 – NSAddict 2014-10-31 23:08:17

回答

2

你必須將其展開兩次

#define xx(x0,x1) x0 ## _ ## x1 
#define x(x0,x1) xx(x0,x1) 
#define Method(y) \ 
    x(CurrentClass,y) 
+0

太棒了!你知道爲什麼這是必要的嗎? – NSAddict 2014-10-31 23:17:19

+1

@NSAddict我可能應該做出這個答案。宏參數擴展時有個例外。看到這[鏈接](http://web.mit.edu/rhel-doc/3/rhel-cpp-en-3/macro-pitfalls.html)。滾動到3.9.6。參數Prescan'。它說「宏參數在被替換成宏體之前是完全宏擴展的,除非它們被串化或粘貼其他標記。在你的例子中,你使用## concatenate,所以參數的預掃描不會導致擴展。通過將它分成2個宏,第一個擴展參數和第二個連接。 – 2014-10-31 23:47:35

+1

@NSAddict:爲了觀察串聯可以防止參數預掃描,請使用您的原始示例'CurrentClass ## _ ## x'並替換爲'CurrentClass x'。雖然這個實驗不是你想要做的,但查看c preprocesor輸出,你應該注意到你得到了'Foo bar()'。它擴大了,因爲我刪除了##(連接)。 – 2014-10-31 23:55:38