2010-10-15 118 views
3

所以說我有一個位的代碼輸出下面很簡單的宏,沿着它:C++恆預處理宏和模板

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3] 
std::cout << SIMPLEHASH("Blah"); 

這個輸出309,如果你查看裝配就可以看到:

00131094 mov   ecx,dword ptr [__imp_std::cout (132050h)] 
0013109A push  135h 
0013109F call  dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (13203Ch)] 

其中135h很好地翻譯成309十進制。一切都被編成了一個常數。


現在,假設你有一個模板類這樣:

template<int X> class Printer{ 
public: 
void Print(){ 
    std::cout << X; 
} 
}; 

那麼下面將很好地打印數32:這兩個東西單獨工作

Printer<32> p; 
p.Print(); 

,當您嘗試將它們合併時,問題就出現了:

#define SIMPLEHASH(STRING) STRING[1] + STRING[2] + STRING[3] 
Printer<SIMPLEHASH("Blah")> p; 
p.Print(); 

在Visual Studio這給出:

1> \ ShiftCompare.cpp(187):錯誤C2975: 'X':爲 '打印機' 無效模板參數,預期編譯時間常量表達式
1> \ ShiftCompare.cpp(127):參見「X」

的聲明儘管SIMPLEHASH("Blah")可以降低到在編譯時的常數,如在第一實施例所示。

那麼,有什麼辦法可以告訴編譯器「先評估這個」?模板在預處理器評估中自然地位於「宏」之前?

有沒有人看到任何方式我可以讓這兩個一起工作?

+1

預處理器是一個紅色的鯡魚。根據該語言,「Blah」[0]不是一個常量表達式;而已。僅僅因爲你的編譯器偶然發現並不意味着什麼。 (這是針對特定實現的結果的問題,並且假設它是由語言保證的。) – GManNickG 2010-10-15 22:33:35

+2

回答「我怎樣才能讓這兩個人一起工作?」部分,如果你能解釋你正在試圖解決的實際問題,這將是有幫助的。如果你無法一起獲得這兩件事情,那麼你可以通過其他方式解決你的問題。 – 2010-10-15 22:35:48

+0

試圖讓hashing函數在工廠類中創建別名(在編譯時)以進行註冊。我試圖給需要註冊的類是一個靜態(模板類)成員s.t.該成員可以在構造函數被調用時將其註冊爲擁有類(靜態,立即在代碼加載時)。顯而易見的另一種方式是使用全局變量而不是靜態成員,而且工作正常,我只是想看看是否有一種方法不會讓全局變量在命名空間中飛行。 – Jason 2010-10-15 23:13:24

回答

5

在源文件完全解析和預處理完全沒有任何與模板有關的事情之前,對宏進行評估。

問題是,您實例化的模板參數Printer必須是常量表達式,並且不能在常量表達式中使用字符串常量。