2009-12-18 27 views
5

我有一個宏,其中一個參數是一個枚舉值,它在未指定名稱空間範圍的情況下給出。然而,在我需要訪問宏的某處(顯然我必須在那裏定義名稱空間),但我似乎無法用模板參數來連接命名空間名稱。鑑於以下示例代碼,編譯器會抱怨pasting :: and Val doesnt give a valid preprocessor token(它可以很好地將get和a進行拼接)。具有名稱空間的Concat宏參數

namespace TN 
{ 
    enum Info 
    { 
     Val = 0 
    }; 
} 

#define TEST(a) TN::Info get ## a(){return TN::##a;} 
TEST(Val) 

所以有任何方法來完成這項工作,而無需使用另一參數,並基本上指定要被使用兩次(例如#define TEST(a,b) TN::Info get ## a(){return b;})的值?

回答

10

##是一個令牌粘貼操作符,即它應該從令牌的多個位中創建一個單獨的令牌,並且如編譯器所說,::Val不是單個令牌,而是兩個令牌。

爲什麼你需要認爲你需要第二個##?這有什麼問題。

#define TEST(a) TN::Info get ## a() { return TN::a; } 
+0

顯然我在想辦法複雜,謝謝 – Grizzly 2009-12-18 14:29:13

+0

@Grizzly:諷刺的是,恰恰相反!我的第一本能也是連接,因爲宏基本上是查找和替換文本替換。當你意識到他們比這更復雜時(因爲他們在_tokens_上工作,而我們的大腦卻不這樣)出現這樣的問題。 :) – 2014-03-19 14:10:16

3

只有當您想要連接兩個項目並讓編譯器將結果視爲單個標記(例如標識符)時才使用##。

在您的宏中,第一次使用##是正確的,因爲您試圖通過粘貼geta的內容來構建標識符,但第二次使用##是虛假的,因爲您只是想要a的內容中的標識符和::運算符是一個獨立的實體。海灣合作委員會會抱怨這個(雖然MSVC++應付)。

#define TEST(a) TN::Info get ## a(){return TN::a;} 

應該工作。

相關問題