2010-09-22 161 views
6

Hallo!具有多個模板參數的C++單模板專業化

我想只專注於兩種模板類型之一。例如。 template <typename A, typename B> class X對於單個功能X<float, sometype>::someFunc()應該有一個特殊的實現。

示例代碼:

main.h:

#include <iostream> 

template <typename F, typename I> 
class B 
{ 
public: 
    void someFunc() 
    { 
     std::cout << "normal" << std::endl; 
    }; 

    void someFuncNotSpecial() 
    { 
     std::cout << "normal" << std::endl; 
    }; 
}; 

template <typename I> 
void B<float, I>::someFunc(); 

main.cpp中:爲class B

#include <iostream> 
#include "main.h" 

using namespace std; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    cout << "special" << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    B<int, int> b1; 
    b1.someFunc(); 
    b1.someFuncNotSpecial(); 

    B<float, int> b2; 
    b2.someFunc(); 
    b2.someFuncNotSpecial(); 
} 

編譯失敗。這是真的,這在C++中是不可能的嗎?什麼是最好的解決方法?

[編輯]

template <float, typename I> void B<float, I>::someFunc();導致 main.h:26:錯誤: '浮動' 不是的模板常量參數

template <typename I> void B<float, I>::someFunc();導致 main.h有效的類型:27:錯誤:使用不完整類型「B類」無效

而我正在使用gcc。

[編輯]

我不想專門全班同學,因爲有沒有一個專業化等功能。

+0

類模板A與您的問題有關嗎? – Doug 2010-09-22 11:51:43

+0

我認爲這會讓問題更容易理解。我將刪除它。 – tauran 2010-09-22 11:53:08

+0

這在stackoverflow上已經被問過幾百次了:)我想我們中的一些人可以設置一個真正的模板常見問題與這樣的問題。人們可以檢查常見問題,看看他們的問題是否得到解答,而不必搜索一個愚蠢的問題。 – 2010-09-23 04:53:39

回答

16

你必須提供類模板B偏特

template <typename I> 
class B<float, I> 
{ 
public: 
    void someFunc(); 
}; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    ... 
} 

你也可以定義someFunc專業化內。

但是,如果你只想專門做一個功能,而不是一個類做e。 G。

template <typename F, typename I> 
void someFunc(F f, I i) { someFuncImpl::act(f, i); } 

template <typename F, typename I> 
struct someFuncImpl { static void act(F f, I i) { ... } }; 

// Partial specialization 
template <typename I> 
struct someFuncImpl<float, I> { static void act(float f, I i) { ... } }; 

但是你不能在沒有這個技巧的情況下專門化一個函數模板。

+1

你無法知道這一點。但在我的使用案例中,還有很多沒有專業化的其他功能。採用這種方法,我將不得不加倍所有這些功能。 – tauran 2010-09-22 12:02:39

+1

@tauran:你不能提供功能模板的部分專業化。僅適用於類模板,並且必須爲整個類再次提供定義。與它一起生活,或看到更新的答案。 – 2010-09-22 12:04:16

+0

您能否在tauran的代碼中說明一件事?有'template void B :: someFunc();'在'main.h'的末尾。我認爲tauran想要聲明,在另一個編譯單元中某個地方定義了專門化。這種東西不需要導出模板嗎?如果專業化意味着要在所有編譯單元中可見,'main.h'包含在內,是不是必須在頭文件中? – 2010-09-22 12:23:48

5

Although you can totally specialize member functions of a class template, you cannot _partially specialize member functions. - Andrei Alexandrescu

專業化由其他海報說明。

你可以,但是,超載使用:

template <class T, class U> T fun(U obj); // primary template 
template <class U> void Fun<void, U>(U obj); // illegal pertial 
// specialization 
template <class T> T fun (Window obj); // legal (overloading) 

如果你想深入到這一點,你可以閱讀關於這個問題的深度「現代C++設計」,由A. Alexandrescu的。

+0

+1用於調用模板重載。這是我很少考慮使用的工具,但在某些情況下可以完成這項工作。 – 2010-09-22 12:12:30

0

解決方案1.將所有實現移動到像B_Base這樣的基類。然後專注於float以覆蓋someFunc。像下面那樣

template <typename F, typename I> 
    class B : B_Base<F, I> 
    { 
    } 

    template <typename I> 
    class B<float, I> : B_Base<flat, I> 
    { 
    public: 
     void someFunc() {....} 
    }; 

解決方法2:使用函數重載,將float作爲輸入或boost :: is_same來分派。不幸的是,你的功能someFunc沒有參數。所以它需要改變界面。