1

模板函數匹配不明原因的變化我有一個包含一個模板函數下面的代碼。當我使用枚舉的第二個參數調用此函數時:在某些情況下,它會查找模板特化,並且在某些情況下它不會。C++與枚舉

我已經驗證了枚舉在兩種情況下都是相同的枚舉(例如沒有重定義)並且其他參數具有正確的值,我發現一個編譯是使用-Winline集合完成的(我沒有嘗試更改它)還有什麼要看?

class A { 
public: 
    template <typename T> 
    int f(uint32_t id, T const& t, bool cond); 

    ... 
}; 

template <typename T> 
int A::f(uint32_t id, T const& t, bool cond) 
{ 
    ... 
} 

template <> 
inline int A::f<int>(uint32_t, int const& t, bool cond) 
{ 
    .... 
} 
+0

您允許其專業類外的函數模板而不在類中聲明的專業化? – 2011-02-10 02:58:12

+0

@Jeremiah Willcock-是的,這是合法的。不過,您只能完全專注於此。我不知道爲什麼標準委員會決定合法。 – templatetypedef 2011-02-10 03:04:14

回答

2

對於初學者來說,通常使用模板專門化作爲重載模板函數的方式是不可取的。模板特化與函數重載很難交互,並且有一些非常神祕的規則指定它們何時被選擇,並且通常認爲只提供常規函數重載比專用函數模板更好。

在這種情況下,我建議改變你的類是這樣的:

class A { 
public: 
    template <typename T> 
     int f(uint32_t id, T const& t, bool cond); 
    int f(uint32_t id, int t, bool cond); 
    ... 
}; 

然後改變你的模板專業化僅僅是過載的實現。由於C++函數重載的方式,這將更準確地選擇正確版本的函數。

至於你的問題,你的代碼並不總是調用重載的原因是C++區分了枚舉類型和類型int。雖然有int S和枚舉類型之間進行轉換的方式,他們是不一樣的東西,並旨在捕捉int秒的過載,不能保證趕上枚舉類型爲好。你可能更適合重載函數來處理枚舉的情況。

0

不是一個試圖回答,但要發佈超過將適合評論...

基本上,這表明預期的行爲(枚舉從未匹配INT專業化)的3.4.6 GCC。你使用什麼編譯器?你能提供一個類似的,完整的程序來產生錯誤嗎?

#include <iostream>                

struct A                   
{                    
    public:                  
    template <typename T>              
    void f(const T&) { std::cout << "general\n"; }        
};                    

template <>                  
void A::f<int>(const int&) { std::cout << "specialised\n"; }      

enum E1 { Zero, One, Two };              

enum E2 { Max = INT_MAX };              

int main()                  
{                    
    A a;                   
    a.f("abc");                 
    a.f(123);                 
    a.f(Zero);                 
    E1 e = Two;                 
    a.f(e);                  
    a.f(Max);                 
} 

輸出:

general 
specialised 
general 
general 
general