C 函式模板特化如何避免重複定義

2021-09-08 16:46:49 字數 2171 閱讀 1785

我正在用乙個基於模板的庫源**,該庫包含一些針對特定型別的模板函式特化。類模板,函式模板和模板函式特化都在標頭檔案中。我在我的.cpp檔案中 #include 標頭檔案並編譯鏈結工程。但是為了在整個工程中使用該庫,我將標頭檔案包含在 stdafx.h 中,結果出現特化模板函式的符號多重定義錯誤。我要如何組織標頭檔案才能避免多重符號定義錯誤?我用 /force:multiple,但我想用乙個更好的解決方法。

lee kyung jun

template int compare(t t1, t t2)

該模板根據地乙個引數是否等於、大於、或小於第二個引數而分別返回零或+/-1。它是典型的用於集合排序時的排序函式。它假設型別 t 具備 operator== 和 operator> 操作,並支援 int,float,double 或 dword 型別。但它不能應用於比較自負串(char* 指標),因為這個函式比較的是串指標,而不是字串本身:

lpctstr s1,s2;

...int cmp = compare(s1,s2); // s1為了能進行字串比較,你需要乙個使用 strcmp 或其 tchar 版本 _tcscmp 的模板特化:

// specialization for strings

template<>

int compare(lpctstr s1, lpctstr s2)

沒錯,這樣做完全正確,現在的問題是:將這個特化放在何處?顯然是要放在模板的標頭檔案中。但這樣會導致符號多重定義的錯誤,就像 lee 遇到的那樣。原因很明顯,模板特化是乙個函式,而非模板。它與下面的寫法是一樣的:

int compare(lpctstr s1, lpctstr s2)

沒有理由不在標頭檔案中定義函式——但是一旦這樣做了,那麼你便無法在多個檔案中 #include 該標頭檔案。至少,肯定會有鏈結錯誤。怎麼辦呢?

如果你掌握了模板函式特化即函式,而非模板的概念,你就會認識到有三個選項,完全與普通函式一樣;特化為 inline,extern 或者 static。例如,像下面這樣:

template<>

inline int compare(lpctstr s1, lpctstr s2)

對於大多數模板庫而言,這是最容易和最常見的解決方案。因為編譯器直接擴充套件內聯函式,不產生外部符號,在多個模組中 #include 它們沒有什麼問題。鏈結器不會出錯,因為不存在多重定義的符號。對於像 compare 這樣的小函式來說,inline 怎麼說都是你想要的(它更快)。

但是,如果你的特化很長,或出於某種原因,你不想讓它成為 inline,那要如何做呢?此時可以做成 extern。語法與常規函式一樣:

// in .h header file

template<>

extern int compare(lpctstr s1, lpctstr s2);

#ifdef mylib_implement_funcs

template<>

int compare(lpctstr s1, lpctstr s2)

#endif

使用該方法,所有模組都包含此標頭檔案,但在包含它之前,只有乙個 #define mylib_implement_funcs。這個方法不支援預編譯頭,因為編譯器用 stdafx.h 中的任何 mylib_implement_funcs 值載入預編譯版本。

避免符號多重定義錯誤的最後同時也是用得最少的乙個方法是將特化做成 static:

template<>

static int compare(lpctstr s1, lpctstr s2)

這樣鏈結器也不會出錯,因為靜態函式不向外界輸出其函式,並且它讓你將所有東西都保持在乙個標頭檔案中,不用引入預處理符號。但它缺乏效率,因為每個模組都有乙個函式拷貝。如果函式小到沒什麼——那為何不用內聯呢?

所以簡言之:將特化做成 inline 或 extern。通常都是用 inline。兩種方法都得編輯標頭檔案。如果使用的是第三方的庫沒有標頭檔案,那麼你除了用鏈結選項 /force:multiple 之外別無選擇。在你等著生成你的工程時,你可以告訴編寫庫檔案的那個傢伙——為什麼要將函式模板特化定義成 inline 或者 extern。就說是我說的。

最後一次種就類結束外面(;)的後面宣告,然後在.cpp中實現,和上面的extern一樣,其實不加extern也是行的,只是乙個宣告就ok了呀

函式模板「偏特化」 (C )

模板是c 中很重要的乙個特性,利用模板可以編寫出型別無關的通用 極大的減少了 量,提公升工作效率。c 中包含類模板 函式模板,對於需要特殊處理的型別,可以通過特化的方式來實現特定型別的特殊操作。最近工作中,需要處理cont這種復合型別和t這種自定義型別的模板特化,因為cont型別有五種左右需要特殊處...

函式模板的特化

函式模板的特化 該定義中乙個或多個模板形參的實際型別或實際值是指定的。特化形式如下 關鍵字template後面接一對空的尖括號 再接模板名和一對尖括號,及括號中指定這個特化定義的模板形參 函式形參表 函式體 template int compare const char const v1,const...

函式模板的特化

include include using namespace std 泛型版本 template int compare const t v1,const t v2 為實參型別 const char 提供特化版本 template int compare const char const v1,c...