2010-08-21 116 views
2

問題在說什麼。另外,是否可以這樣做內聯?如何根據類模板參數專門化成員函數

這裏是一個小例子只是爲了給一個想法......

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void do(const Foo<T> &f) { 
    z = f.z; 
    } 
    // specialize 'do' for Foo<int>, possible inline? 

private: 
    T z; 
}; 
+0

AFAIK是不可能的。 – Tronic 2010-08-21 00:10:38

+5

請注意,您的函數不能命名爲'do',因爲'do'是一個關鍵字。 – 2010-08-21 00:18:56

+0

忘掉內聯。 Inline是一個我們作爲程序員應該忽略的概念,並留給最高級的電腦神(作爲編譯器的AKA) – 2010-08-21 00:37:41

回答

3

您可以排序的通過使成員函數的成員函數模板,使用SFINAE(替換故障得到這個行爲是不是一個錯誤)。例如:

template <typename U> 
typename std::enable_if<!std::is_integral<U>::value && 
         std::is_same<T, U>::value, void>::type 
f(const Foo<U>& x) 
{ 
} 

template <typename U> 
typename std::enable_if<std::is_integral<U>::value && 
         std::is_same<T, U>::value, void>::type 
f(const Foo<U>& x) 
{ 
} 

is_integral型性狀測試是否U是整數類型。如果不是,則首先實例化;如果是,則第二個被實例化。

is_same型性狀測試確保TU是相同的類型。這用於確保成員函數模板沒有爲除Foo<T>以外的任何類型實例化。

本示例使用C++ 0x <type_traits>庫; Boost也有a type traits library,你可以使用,其工作大部分是相同的。

+0

謝謝!我不得不說,如果語法是這樣的話,我很可能最終會用我的選擇。 – floogads 2010-08-21 01:08:01

+0

我沒有看到std :: enable_if。看起來它沒有成爲標準的一部分。 – Brent 2013-02-13 18:02:36

+0

@Brent:是的。它在''中定義。 – 2013-02-13 18:58:07

-1

你可以嘗試做這樣的事情(未測試,可能無法正常工作):

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    template<typename Ty = T> 
    void do(const Foo<T> &f) { 
    z = f.z; 
    } 

    template<> 
    void do<int>(const Foo<T> &f) { 
    //specialized code 
    } 

private: 
    T z; 
}; 
+0

專業化是不需要的,這可以使用重載來完成。重載的問題是你必須重載每個整型的成員函數。可能有多達十二種整數類型(或更多;我用完手指後不久就失去了蹤跡),這是很多必須寫的過載。 – 2010-08-21 00:21:32

+2

事實上,它不會那樣工作。我永遠不會明白爲什麼人們發佈他們不知道的代碼是有效的。提問者也可以做到這一點。 – 2010-08-21 02:20:45

+0

這裏有兩個問題:你不能專注於內聯成員模板,如果沒有完全專門化包含的類,你不能專門化它們。 – 2010-08-21 08:58:05

3

你不需要做複雜的事情。只需使用重載和委派。請注意,我們不能只加一個int過載,當T原來因爲證明是int過,這將是一個無效的過載(具有相同簽名的兩個功能)

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void doIt(const Foo<T> &f) { 
    doItImpl(f); 
    } 

private: 
    template<typename U> 
    void doItImpl(const Foo<U> &f) { 
    z = f.z; 
    } 

    void doItImpl(const Foo<int> &f) { 
    /* ... */ 
    } 

private: 
    T z; 
}; 

或者,這種情況下,你可以做這由專業化

template<typename T> 
class Foo { 
public: 
    Foo() :z(0.0) {} 

    void doIt(const Foo<T> &f) { 
    z = f.z; 
    } 

private: 
    T z; 
}; 

template<> 
inline void Foo<int>::doIt(const Foo<int> &f) { 
    /* ... */ 
} 

使用專業化這種方式是唯一可能的,如果所有的模板參數是固定的。換句話說,部分專門化成員函數是不可能的。