2011-04-01 185 views
69

我需要專門化某種類型的模板成員函數(比如說double)。它工作正常,而類X本身不是一個模板類,但是當我做模板GCC開始給編譯時錯誤。模板類成員函數的顯式特化

#include <iostream> 
#include <cmath> 

template <class C> class X 
{ 
public: 
    template <class T> void get_as(); 
}; 

template <class C> 
void X<C>::get_as<double>() 
{ 

} 

int main() 
{ 
    X<int> x; 
    x.get_as(); 
} 

這裏是錯誤消息

source.cpp:11:27: error: template-id 
    'get_as<double>' in declaration of primary template 
source.cpp:11:6: error: prototype for 
    'void X<C>::get_as()' does not match any in class 'X<C>' 
source.cpp:7:35: error: candidate is: 
    template<class C> template<class T> void X::get_as() 

我怎樣才能解決這個問題,什麼問題在這裏?

在此先感謝。

+2

這是在當前的標準是非法的,要專門化,你必須專門的課以及... – Nim 2011-04-01 11:55:00

+0

但它的作品,如果類不是模板。它也是非法的嗎? – ledokol 2011-04-01 11:58:43

+0

nope,這非常好,只適用於此規則適用的類模板(AFAIK)。 – Nim 2011-04-01 12:01:09

回答

85

它不這樣工作。您需要下面要說的,但它是不正確

template <class C> template<> 
void X<C>::get_as<double>() 
{ 

} 

明確specialized members需要它們周圍的類模板被明確專門爲好。所以你需要說出以下內容,這將只針對X<int>的會員。

template <> template<> 
void X<int>::get_as<double>() 
{ 

} 

如果你想保持周圍的模板未被專門化,你有幾個選擇。我更喜歡重載

template <class C> class X 
{ 
    template<typename T> struct type { }; 

public: 
    template <class T> void get_as() { 
    get_as(type<T>()); 
    } 

private: 
    template<typename T> void get_as(type<T>) { 

    } 

    void get_as(type<double>) { 

    } 
}; 
+0

你爲什麼需要'type <>'wrapper?一個0的類型轉換爲'T'類型的指針是不是有訣竅?我想這不是優雅的... – Nim 2011-04-01 12:08:23

+0

看起來這是真的不可能做到。謝謝。 – ledokol 2011-04-01 12:09:04

+3

@Nim對,我認爲指針投射的東西是醜陋的,並且不適用於你不能形成指針(引用)的類型。此外,在C++中,讓函數參數成爲不帶大小的數組類型的指針是非法的。將它放在一個類型包裝器中可以適用於所有類型。 – 2011-04-01 12:09:07

13

如果一個人能夠使用std::enable_if我們可以依靠SFINAE(替換故障是不是一個錯誤)

,將工作像這樣:

#include <iostream> 
#include <type_traits> 

template <class C> class X 
{ 
public: 
    template <class T, typename std::enable_if< ! std::is_same<double,T>::value>::type * = nullptr > void get_as(){ 
     std::cout << "get as T" << std::endl; 
    } 


    template <class T, typename std::enable_if< std::is_same<double,T>::value>::type * = nullptr > void get_as(){ 
     std::cout << "get as double" << std::endl; 
    } 
}; 


int main() 
{ 

    X<int> d; 
    d.get_as<double>(); 

    return 0; 
} 

醜陋的東西是所有這些enable_if只有一個專業化需要可用於編譯器否則消除歧義錯誤將會出現。這就是爲什麼默認行爲「得到T」還需要啓用if。

相關問題