2013-05-27 123 views

回答

13

每個專業化都會帶來一種全新的數據類型(或者如果專業化只是部分的話,則是一個全新的模板)。從標準(C++ 11):

(§14.5.5/ 2)每一類模板部分特例是一種獨特的模板,並應用於模板部分特例的成員提供的定義(14.5.5.3 )。

和:

(§14.5.5.3/ 1)[...]類模板偏特的成員是無關的主模板的成員。應定義以需要定義的方式使用的類模板部分專業化成員;主模板成員的定義從來不會用作類模板部分專業化成員的定義。 [...]

以上是在部分專業化的背景下說的,但它適用於明確的專業化(如你的情況),以及,雖然標準沒有說得很清楚。

另外請注意,您不僅需要聲明的是,你在一個專業化希望所有成員函數,但是你需要定義他們,太(這裏,標準是非常明確的,甚至關於明確的專門化):

(14.7.3/5)明確專用類的成員不是從類模板的成員聲明中隱式實例化的;相反,類模板專業化的成員本身應該明確定義,如果它的定義是必需的。在這種情況下,類模板顯式專業化的定義應在成員定義的位置 範圍內。明確專門化的類的定義與生成的專業化的定義無關。也就是說,其成員不必具有與生成的專業化的成員相同的名稱,類型等。 [...]

所以,的確,A<int>只會有method2(),並A<float>只會有method1()作爲成員。此外,如果您要在A<int>專業化中引入method1(),則它不需要具有與A<float>::method1()相同的參數類型或返回類型。

請參閱@ aschepler的答案,以避免必須重寫int案例的模板定義。

+1

@Fellowshee是的,你可以做到這一點。在這種情況下,不申報新的'模板<>結構一個 {...};',而只是聲明(和定義)要專門的方法:'一個 ::方法1(){.. 。};類外部模板定義。 – jogojapan

+0

有趣的是,課堂內部沒有提及的課堂外聲明和定義被認爲是合法的? – johnbakers

+0

@Fellowshee哦,對不起,我以爲你需要在'int'情況下使用'method1'的專門化。如果你真的需要爲'int'情況添加一個全新的'method2',那麼的確需要重寫整個模板int。根據情況,最好將'method2'添加到主模板定義中,但將其保留爲未定義(或讓它拋出異常,或放入'static_asssert(false,「not implemented」);後者只適用於C++ 11))。這樣你可以專注於'int'情況下的'method2'而不必重寫整個模板。 – jogojapan

1

專業化取代了通用模板。所以A<int>將只有method2(),當然,A<double>將只有method1()

+0

我想那麼編譯器將把它們作爲完全獨立的班級,他們之間沒有任何關係,因爲如果他們有完全不同的名字(這在創建的源,他們可能做什麼?) – johnbakers

+0

從模板生成的每個類型是完全與同一模板生成的其他類型完全沒有關係。這沒有什麼區別。 '一個','一個'和'一個'是三個不相關的類。 – Gorpik

9

@ jogojapan的答案解釋了語言的作用。這裏有一對夫婦的解決方法,如果你想添加新的成員,具體分工:

template<typename T> 
struct A_Base { 
    void method1() {} 
}; 

template<typename T> 
struct A : public A_Base<T> {}; 

template<> 
struct A<int> 
    : public A_Base<int> 
{ 
    void method2() {} 
}; 

現在A<int>擁有會員method1method2,但A<float>沒有method2

OR(如果你可以修改主模板)...

#include <type_traits> 

template<typename T> 
struct A { 
    void method1() {} 

    template<int N=0> 
    auto method2() -> 
    typename std::enable_if<std::is_same<T, int>::value && N==N>::type 
    {} 
}; 

template<int N>N==N零件確保std::enable_if有一個相關的值,因此不會抱怨,直到有人竟試圖使用A<T>::method2與一個不正確的T參數。

+0

+1,尤指爲enable-if技術。 – jogojapan

+0

@aschepler - 如果'A_Base' *不是*模板,第一種技術(非C++ 11技術)會工作嗎?也就是說,你可以有一個'A :: A_Base :: method2'嗎?我從MSVC中收到一個錯誤,我從來沒有看到錯誤([C2936](https://msdn.microsoft.com/en-us/library/ctfzt48x.aspx))。我不確定它不可能,不可能用C++ 03,或者它是MSVC的限制。 – jww

+0

@jww是的,它應該工作。我不確定爲什麼你會得到這個錯誤。您鏈接的頁面建議檢查不匹配的大括號。如果你還沒有看到一個愚蠢的錯誤,你可能想編寫和測試一個[mcve]併發佈一個關於它的新問題。 – aschepler