2016-10-07 53 views
3

我在編譯下面的例子時遇到一個奇怪的問題。0模板函數模糊參數扣除

template<typename T> 
struct identity { 
    typedef T type; 
}; 

template<typename T> 
void foo(typename identity<T>::type v) {} 

template<typename T> 
void foo(typename identity<T>::type* v) {} 

int main() { 
    foo<int>(0); 
    foo<short>(0); 
    return 0; 
} 

調用foo<int>(0)編譯,但是,當我打電話foo<short>(0)如果爲0值或指針編譯器無法推斷。我使用身份強制顯式指定模板參數。編譯器(msvc)錯誤信息:

error C2668: 'foo': ambiguous call to overloaded function 

它是編譯器錯誤嗎?

回答

3

這是不是一個編譯器的bug。這是由於將0轉換爲指針類型具有「轉換等級」的事實。

下用零值 或類型的std的prvalue :: nullptr_t ++ 11§4.10(轉換秩)

空指針常數是文字的整數(2.13.2)。空指針常量可以被 轉換爲指針類型;結果是空指針值爲 ,該類型的空指針值可以與對象 指針或函數指針類型的每個其他值區分開來。這種轉換被稱爲空指針轉換 。

所以,當你寫一個0文字和轉換是必要的,編譯器遇到相同級別的兩個重載 - 一個非指針類型,另一個指針類型。

一些例子:

foo<short>((short)0); // No conversion necessary: allowed 
foo<nullptr_t>(nullptr); // No conversion necessary: allowed 
foo<nullptr_t>(0); // ambiguous 
foo<nullptr_t>(NULL); // ambigious - another reason to stop using NULL