2017-04-10 68 views
3

我有這樣的代碼:爲什麼在頭文件結構中聲明的模板不會違反ODR和專業化?

#include <iostream> 

struct A 
{ 
    template<typename T> bool isImplemented() 
    { 
       std::cout << "Not Implemented" << std::endl; 
       return false; 
    } 
}; 

template<> inline bool A::isImplemented<int>() 
{ 
    std::cout << "int Implemented" << std::endl; 
    return true; 
} 

我可以理解爲什麼模板專業化需要在線,以阻止ODR被侵犯的直列將合併轉換表,避免衝突。

但是,爲什麼我不需要在結構體A內部isImplemented上內聯? 也許這個問題可以擴展到,爲什麼如果方法是在頭部的struct/class中聲明的,它不需要內聯? 據我所知,它會在每個被調用的目標文件(.o)上創建符號,違反ODR,爲什麼不會發生?

+3

任何與模板參數本質上是隱式的「內聯」。 – aschepler

+2

模板專業化是一種功能。該模板是一個模板。模板不是功能,反之亦然。模板遵循不同的規則。 –

+0

@KerrekSB,實際上幫助很多,謝謝。我在試圖理解爲什麼我只需要專業化的問題。我想象這是適用於您聲明朋友操作符時的相同規則,並且您需要使用內聯以防止ODR上的違規行爲,對嗎? – Lefsler

回答

3

你不需要它的原因有兩個:

  • 類的定義中定義的每個函數是隱含inline
  • 模板不需要inline關鍵字。請記住,你的原始功能是一個模板,而專業化則不是。
1

在此強調的一點是,template<typename T> bool isImplemented()不是一個函數。 它是一個函數的模板,並且只會專門存在(如代碼),就像您使用template<> inline bool A::isImplemented<int>()所做的一樣。

inline這裏不是強制性的。程序編譯和運行完美沒有它。

奇怪的是你的struct A不依賴於任何模板參數既不isImplemented()方法,所以我仍然試圖找出你的意圖。

你的函數的簡單用法可能是這樣的:

int main() 
{ 
    A a; 

    a.isImplemented<int>(); 
    a.isImplemented<double>(); 
} 

和輸出:

int Implemented 
Not Implemented 

,基本上你能告訴你已經明確地從一般的人實施至極特。這是你需要的嗎?

編輯:

鑑於我的回答的評論,我相信原來的問題是很好的回答在這裏:

+0

其實,這是我寫的代碼,用於理解內聯和ODR。這就是爲什麼它是這樣的。它來自我很久以前試圖根據返回類型專門化一些東西的問題。 – Lefsler