2014-08-29 111 views
1

我可以找到很多模板類的部分專業化的幫助,但我想部分專門化一個非模板類的方法。如何部分專門化非模板類的模板成員方法?

class TempMembMeth { 
    public: 
    template<typename T1, typename T2> 
    void templMethod1(int); 
}; 

我的模板化方法實現:

template<typename T1, typename T2> 
    void TempMembMeth::templMethod1(int){ 
    std::cout << "<T1,T2>templMethod1(int)" << '\n'; 
} 

我完全符合規範的方法確定:

template<> 
inline void TempMembMeth::templMethod1<char,char>(int){ 
    std::cout << "<char,char>templMethod1(int)" << '\n'; 
} 

可是我該怎麼辦部分規格?

template<typename T2> 
inline void TempMembMeth::templMethod1<char,T2>(int){ 
    std::cout << "<char,?>templMethod1(int)" << '\n'; 
} 

我得到:「TempMembMeth :: templMethod1」:非法使用顯式模板參數 我無法與部分專業方法重新定義類,因爲該類沒有模板。它也不會讓我「重載」類中的模板化方法 - 它又抱怨非法使用顯式模板參數。

所以,如果這是可能的任何想法? 目前,我通過模板化課程來圍繞它工作,但我想知道如果沒有模板課程,這是否可能。

+2

不能部分專門函數模板。 – 2014-08-29 15:46:27

+0

[爲什麼函數模板不能部分專用?]的可能重複(http://stackoverflow.com/questions/5101516/why-function-template-cannot-be-partially-specialized) – IdeaHat 2014-08-29 15:48:05

+1

您可以將實現轉發到模板(幫助者)類而不是整個類的模板。 – Jarod42 2014-08-29 15:56:49

回答

1

正如其他人已經注意到的,您不能部分地專注於函數模板。但是,您可以使用幾乎具有相同效果的助手類。

#include <iostream> 

namespace details 
{ 
    // Forward declaration of the helper class. 
    template<typename T1, typename T2> struct Helper; 
} 

class TempMembMeth 
{ 
    public: 

    template<typename T1, typename T2> 
    void templMethod1(int arg) 
    { 
     details::Helper<T1, T2>::doit(this, arg); 
    } 
}; 

namespace details 
{ 
    // Implement the helper class and its specializations. 
    template<typename T1, typename T2> struct Helper 
    { 
     static void doit(TempMembMeth* obj, int arg) 
     { 
     std::cout << "In Helper<T1,T2>::doit()\n"; 
     } 
    }; 

    template<typename T2> struct Helper<char, T2> 
    { 
     static void doit(TempMembMeth* obj, int arg) 
     { 
     std::cout << "In Helper<char,T2>::doit()\n"; 
     } 
    }; 

    template<> struct Helper<char, char> 
    { 
     static void doit(TempMembMeth* obj, int arg) 
     { 
     std::cout << "In Helper<char, char>::doit()\n"; 
     } 
    }; 
} 

int main() 
{ 
    TempMembMeth obj; 
    obj.templMethod1<float, int>(10); 
    obj.templMethod1<char, double>(20); 
    obj.templMethod1<char, char>(30); 
    return 0; 
} 

輸出:

In Helper<T1,T2>::doit() 
In Helper<char,T2>::doit() 
In Helper<char, char>::doit() 
+0

這似乎是一個非常乾淨的解決方案。細節命名空間可以匿名以簡化它。同樣在實踐中,輔助類可能需要成爲TempMembMeth類的朋友。 – StephenD 2014-08-30 18:08:43

1

隨着TC的評論,你不能部分專門化模板功能。

您應該使用重載。如有必要,您可以添加一些帶有Type2Type參數的私有函數。例如:

#include <iostream> 

struct Test 
{ 
public: 

    template<typename T1, typename T2> 
    void templMethod1(int i) 
    { 
     templMethodImpl(i, Type2Type<T1>(), Type2Type<T2>()); 
    } 

private: 

    template<typename T> 
    struct Type2Type 
    { 
     typedef T OriginalType; 
    }; 

    template<class T1, class T2> 
    void templMethodImpl(int i, Type2Type<T1>, Type2Type<T2>) 
    { 
     std::cout << "t1 any, t2 any" << std::endl; 
    } 

    template<class T2> 
    void templMethodImpl(int i, Type2Type<char>, Type2Type<T2>) 
    { 
     std::cout << "t1 char, t2 any" << std::endl; 
    } 

    void templMethodImpl(int i, Type2Type<int>, Type2Type<char>) 
    { 
     std::cout << "t1 int, t2 char" << std::endl; 
    } 
}; 

int main() 
{ 
    Test test; 

    test.templMethod1<char, char>(5); 
    test.templMethod1<int, char>(5); 
    test.templMethod1<char, int>(5); 
    test.templMethod1<int, int>(5); 
} 
+0

謝謝。一種生成虛擬類型參數的簡單方法。 Type2Type結構可以留空。我認爲函數調用會涉及編譯器將僞類型參數推送到堆棧上。或者,優化器會將它們忽略爲匿名參數? – StephenD 2014-08-30 18:05:50