2010-06-10 25 views
4

是否有可能做這種專業化?
如果是這樣,怎麼樣?C++模板成員專業化 - 這是一個編譯器限制嗎?

有問題的專門標記//這種專業化將無法編譯 我使用VS2008,VS2010,GCC 4.4.3既不可以編譯此。

我知道我可以通過重載來避免這個func但我想知道是否有辦法用模板專業化來做到這一點。 (不切實際/不可取的,雖然它可能是)

#include<iostream> 
#include<string> 

using namespace std; 

template <typename ALPHA> 
class klass{ 
    public: 
     template <typename BETA> 
     void func(BETA B); 
}; 

template <typename ALPHA> template <typename BETA> 
void klass<ALPHA>::func(BETA B){ 
    cout << "I AM A BETA FUNC: " << B <<endl; 
} 

//THIS SPECIALIZATION WILL NOT COMPILE 
template <typename ALPHA> template <> 
void klass<ALPHA>::func(string B){ 
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl; 
} 

int main(){ 
    klass<string> k; 
    k.func(1); 
    k.func("hello"); 
    return 0; 
} 
+0

如果您將專業化更改爲'void klass :: func (string B);'?這樣它就是一個功能模板的全面專業化(在模板類中)。至少,我想,我現在沒有編譯器。 – Pieter 2010-06-10 14:55:26

+0

用g ++示例編譯器沒有錯誤。 – sth 2010-06-10 15:01:26

回答

3

要回答您在標題中提問的問題:不,這不是編譯器限制。這是一種語言限制。在C++中,爲了明確地專門化嵌套模板(是類模板或成員函數模板),您還必須明確地專門化封閉模板。

您正試圖顯式專門化嵌套模板而不專門使用封閉模板。這不會編譯。

當談到成員函數模板時,當模板參數與某個函數參數(如你的情況)相關聯時,你可以經常用重載來替換顯式的特化,正如泰勒的答案所建議的。在其他情況下,您必須使用其他解決方法。

6

只是使string版本的func與模板版本超載常規非模板成員函數:

#include<iostream> 
#include<string> 

using namespace std; 

template <typename ALPHA> 
class klass{ 
    public: 
     template <typename BETA> 
     void func(BETA B); 
     void func(string b); 
}; 

template <typename ALPHA> template <typename BETA> 
void klass<ALPHA>::func(BETA B){ 
    cout << "I AM A BETA FUNC: " << B <<endl; 
} 

template <typename ALPHA> 
void klass<ALPHA>::func(string B){ 
    cout << "I AM A SPECIAL BETA FUNC: " << B <<endl; 
} 

int main(){ 
    klass<string> k; 
    k.func(1); 
    k.func("hello"); 
    return 0; 
} 

除了它編譯,這裏還有一個好處,你會得到更直觀的行爲。見"Why Not Specialize Function Templates?" from GOTW

編輯:要直接回答您的原始問題,不,這不是一個編譯器限制,它是C++標準不允許的。

C++標準,14.7.3/18表示(部分):

在一個顯式特 聲明一類 模板的成員或 出現在命名空間範圍的成員模板,成員 模板和它的一些封閉 類模板可以保持 非特,除了的 聲明不得明確 專業類成員模板,如果 其包含的類模板並不是 也是明確專用的。

這意味着,自klass是一個模板,你不能沒有也專門klass專門klass::func

+0

這不起作用,k.func(「hello」);將調用模板函數而不是重載函數。 – LoudNPossiblyWrong 2010-06-10 15:02:55

+1

由於'「hello」'是一個'const char *',而不是'string'。爲'const char *'添加另一個重載,或者調用爲'k.func(string(「hello」))''。 – 2010-06-10 15:04:39