2017-09-24 61 views
9

對於以下的代碼:曖昧呼叫用參數(常量T&,常量T&)或(常量字符(&)[N],常量字符(&)[M])

#include <iostream> 
using std::cout; using std::endl; 

template <typename T> 
int compare(const T&, const T&) { 
    cout << __PRETTY_FUNCTION__ << endl; 
    return 0; 
} 
template <size_t N, size_t M> 
int compare(const char (&)[N], const char (&)[M]) { 
    cout << __PRETTY_FUNCTION__ << endl; 
    return 0; 
} 

int main(int argc, char *argv[]) { 
    compare("hi", "is"); 
} 

當我編譯代碼g++ -std=c++1y,它抱怨:

error: call of overloaded ‘compare(const char [3], const char [3])’ is ambiguous 
    compare("hi", "is"); 

根據模板重載的規則,可行的功能是:

compare(const T&, const T&) with T = char [3] 
compare(const char (&)[N], const char (&)[M]) with N = 3ul, M = 3ul 

他們都爲呼叫提供了同樣好的(即確切的)匹配。所以我應該檢查哪一個更專業。

但根據我有限的知識,const T&const char (&)[N]更普遍。所以我認爲compare(const char (&)[N], const char (&)[M])更專業。但爲什麼這個呼籲含糊不清?

回答

10

第一次重載compare(const T&, const T&)強制這兩個參數是相同的類型,而第二次重載不是。所以在這方面,第一個過載更具體。

但是,第二次過載迫使兩個參數都是char數組,所以它在這方面更具體。

因此,無論超載都可以說是比另一個更專業化,結果是模糊性錯誤。

另一種看待它的方法是每個重載都可以接受另一個不允許的輸入:只有第一個重載纔會接受一個調用,其中這兩個參數都是int&。只有第二個超載才能接受參數爲char (&)[2]char (&)[3]的呼叫。

如果你改變了第二超載

template <size_t N> int compare(const char (&)[N], const char (&)[N]) 

會修正這個錯誤,因爲這是現在嚴格比第一超負荷更具體。

+0

我同意的解釋,但解決方案限制使用第二個'比較'大小相等的字符串。 – xtofl

+0

謝謝。我可能已經理解了「專業化」這個詞的意思。但是C++中「專業化」的確切規則是什麼?我沒有閱讀C++的規範。我正在閱讀C++入門書。 – zhenguoli

+0

@xtofl這是解決錯誤的一種方法。另一個例子是將第一個重載改爲兩種不同的類型。在不知道要求的情況下,我無法給出滿足這些要求的解決方案。 – interjay