2013-04-18 51 views
3

我嘗試創建與像可變參數一個EXTERN的模板:與可變參數的extern模板不編譯

extern template<typename... XS> void log(XS... xs); 

但是GCC 7.2不編譯它,並顯示錯誤:

error: expected unqualified-id before ‘<’ token 

我檢查了C++ 11中的gcc狀態,並且extern模板應該可以工作,不是嗎?

回答

6

extern關鍵字做的事情與你的期望不同 - 當然,如果我理解正確,你期望的是什麼。

extern關鍵字應用於顯式實例化的模板,它可以防止編譯器在處理某個翻譯單元時隱式生成該模板的代碼。每一段中的C++ 11標準的14.7.2/2:

There are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration. An explicit instantiation declaration begins with the extern keyword.

沒有extern關鍵字,編譯器會生成在包含調用log(double, int)每個翻譯單元,用於(比方說)log(double, int)代碼,和該代碼 - 對所有翻譯單元來說都應該是相同的 - 最終會被鏈接器合併(鏈接器基本上會丟棄所有的重複項並只保留一個)。

extern關鍵字告訴編譯器把你從這些廢物的編譯時間:「相信我,別人會在其他地方實例化這個模板 - 你不需要做現在」。 但是,這個承諾必須履行

因此,舉例來說,如果你有這樣的主模板:

template<typename... Xs> void log(Xs... xs); 

並且聲明這顯式實例:

extern template void log(int, double); 

比你必須有一些翻譯單元對應的顯式實例:

template void log(int, double) 

否則,編譯器將永遠不會產生代碼log<int, double>(int, double),鏈接器會抱怨未定義的引用。

+0

是的,你得到它rigth。我的意圖是在頭文件中聲明extern,然後在.cpp文件中定義。我發現這是不允許的,因爲它應該有明確的參數。 – Zhen

+2

@ Zhen:是的,不幸的是,允許您將模板定義放入'.cpp'文件的唯一情況是您爲所有模板實例化創建了一個顯式實例化,否則這些實例化將以隱式方式生成。 C++ 03有一個名爲'export'的關鍵字來解決這個問題,但是對於編譯器供應商來說它很難支持它(只有基於EDG的編譯器),所以它在C++ 11中被移除了 –

+1

@AndyProwl--在實施它之後,EDG提出了刪除它的建議。 –