2015-11-11 12 views
1

我有這樣的情況,即我有一個對所有類型的數據類型都適用的現有模板類。但是現在我需要將它專門化爲來自特定類的類。但是並不是所有的班級都應該是專業化的,而只是一些功能。模板類中的C++專用單一方法

我試圖按照this post中描述的方式去做。

class BaseClass 
{ 
    public: 

    bool DoSomething() 
    { 
     return true; 
    } 
}; 

class SubClass : BaseClass 
{ 
}; 

template<typename T, typename _Alloc = std::allocator<T>> 
class TemplateClass 
{ 
    public: 
    template<typename U = T, typename std::enable_if< 
     !std::is_base_of<BaseClass, U>::value>::type> 
    void print_line() 
    { 
     std::cout << "Parameter of general Type T" << std::endl; 
    } 

    template<typename U = T, typename std::enable_if< 
     std::is_base_of<BaseClass, U>::value>::type> 
    void print_line() 
    { 
     std::cout << "Parameter of specific Type BaseClass" << std::endl; 
    } 
}; 

我嘗試使用模板是這樣的:

TemplateClass<BaseClass>* tc1 = new TemplateClass<BaseClass>(); 
tc1->print_line(); 

TemplateClass<SubClass>* tc2 = new TemplateClass<SubClass>(); 
tc2->print_line(); 

TemplateClass<int>* tc3 = new TemplateClass<int>(); 
tc3->print_line(); 

對於每一個函數調用我的錯誤有沒有發現擬合方法。 另一點是,在this article他們說enable_if不應該用於實現之間進行選擇。

有沒有人有想法我的錯誤是什麼或如何正確地做到這一點? 在此先感謝!

+0

你有沒有試過標籤調度? – zahir

回答

1

您可以將其更改爲

template<typename U = T, typename std::enable_if< 
    !std::is_base_of<BaseClass, U>::value>::type* = nullptr> 
void print_line() 
{ 
    std::cout << "Parameter of general Type T" << std::endl; 
} 

template<typename U = T> 
typename std::enable_if<!std::is_base_of<BaseClass, U>::value, void>::type print_line() 
{ 
    std::cout << "Parameter of general Type T" << std::endl; 
} 

,並相應另一個。

兩者背後的想法是在實例化函數模板期間爲其中一個方法產生錯誤。由於錯誤,在重載解析期間不考慮相應的方法,因此只有一個方法(不產生錯誤的方法)可用,然後將被調用。 std::enable_if被用來產生這個錯誤,因爲如果它的第一個參數是false它沒有定義一個type成員,所以函數模板不能被實例化,並且將從重載解析中被移除。

搜索SFINAE獲取更多詳細信息。

+0

這在我上面描述的測試項目中工作。但是當我嘗試在兩種可能性中的一種中實現它時,我總是得到「C4519默認模板參數只允許在類模板上」。 當我這樣做︰ template typename std :: enable_if :: value,iterator> :: type 我得到錯誤「C2039'類型':不是成員'std :: enable_if <_Test,_Ty>'' 你知道爲什麼它不適用於生產性項目嗎?班級簽名與之前所述的一樣。 –

+0

對不起,我看到我的錯誤,我忘了更換'value_type'... –