2015-07-05 38 views
2

我有以下代碼重載模板函數錯誤重載模板函數被調用

#include <iostream> 
using namespace std; 

template <class T> 
const T& max(const T& a1, const T& a2) 
{ 
    cout << "general template" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
const T* max(const T* a1, const T* a2) 
{ 
    cout << "max for pointers" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
const T& max(const T& a1, const T& a2, const T& a3) 
{ 
    cout << "general template with three parameters" << endl; 
    return ::max(::max(a1, a2), ::max(a1, a2)); 
} 

int main() 
{ 
    int* a = new int(5); 
    int* b = new int(56); 
    int* c = new int(2); 
    int*const &g = ::max(a, b, c); 
    cout << *g << endl; 

    return 0; 
} 

,我希望它失敗,因爲有三個參數最大模板將返回引用給一個臨時變量(由模板返回爲指針)。但它起作用並調用通用模板函數。
問題是爲什麼不叫模板指針?

謝謝。

+0

我會避免'使用命名空間標準;',甚至更多當你聲明具有衝突名稱的函數('std :: max'存在)。 – Jarod42

+0

感謝您的諮詢。我只是在測試模板功能。 – user1289

回答

2

如果您註釋掉引用的雙參數max的定義,您會看到代碼無法編譯。是MSVC++ 2013提供了在22行的錯誤是:

error C2440: 'return' : cannot convert from 'const int *' to 'int *const &' 

這似乎是爲什麼max爲引用總是選擇理由:max爲指針模板替換失敗。 如果你的代碼更改爲以下,則指針模板被稱爲:

#include <iostream> 
using namespace std; 

template <class T> 
T max(const T& a1, const T& a2) 
{ 
    cout << "general template" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
T* max(T* a1, T* a2) 
{ 
    cout << "template for pointers" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
T max(const T& a1, const T& a2, const T& a3) 
{ 
    cout << "general template with three parameters" << endl; 
    return ::max(::max(a1, a2), a3); 
} 

int main() 
{ 
    int* a = new int(5); 
    int* b = new int(56); 
    int* c = new int(2); 
    int* g = ::max(a, b, c); 
    cout << *g << endl; 

    return 0; 
} 

如果您註釋掉模板指針的定義,然後引用模板被調用。由於類型已經是一個指針,因此模板的指針優先於模板的引用似乎發生。

這裏是模板匹配的訂單上的解釋:What are the rules for choosing from overloaded template functions?

編輯:OP的代碼可以以另一種方式被改變,從而使MSVC++ 2013更喜歡基於參考的模板,基於指針:

#include <iostream> 
using namespace std; 

template <class T> 
T max(const T& a1, const T& a2) 
{ 
    cout << "general template" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
const T* max(const T* a1, const T* a2) 
{ 
    cout << "template for pointers" << endl; 
    return (a1 < a2) ? a2 : a1; 
} 

template <class T> 
T max(const T& a1, const T& a2, const T& a3) 
{ 
    cout << "general template with three parameters" << endl; 
    return const_cast<const T>(::max(::max(a1, a2), a3)); 
} 

int main() 
{ 
    int* a = new int(5); 
    int* b = new int(56); 
    int* c = new int(2); 
    int* g = ::max(a, b, c); 
    cout << *g << endl; 

    return 0; 
} 

發生這種情況是因爲在此版本中,基於指針的模板定義具有其參數類型的其他限定符:它們不僅僅是T*,而是const T*

+0

頂層const不是匹配的一部分,我認爲它會更清晰地取出 –

+0

@MattMcNabb,你是什麼意思的「頂級常量」? –

+0

正如'T * const a1' –

2

這不起作用。它似乎在工作,因爲你只使用前兩個參數或三個參數max函數。

template <class T> 
const T& max(const T& a1, const T& a2, const T& a3) 
{ 
    cout << "general template with three parameters" << endl; 
    return ::max(
     ::max(a1, a2), 
     ::max(a1, a2)); // HERE 
} 

更正顯示正在發生什麼:您正在比較指針地址。

參見here in action

你的指針過載不會被調用,因爲參考版本更適合:a1 etc是常量引用(指針,但很好)。所以參考版本在超載分辨率方面是完美的匹配。

我想要達到你想要的東西,你需要一些SFINAE魔法。


有一兩件事我想補充:因爲比較指針是C++中的頻繁操作,恕我直言,這將是非常誤導相比之前有一些max取消引用指針。

1

,當你調用max(a, b, c)Tmax(const T& a1, const T& a2, const T& a3)成爲int *的別名,所以在最大(常量牛逼& A1,常量牛逼& A2,常量牛逼& A3) max(a,b)將匹配max(const T& a1, const T& a2)


typedef int * T; 
const T x; 
const int * y; //they are deffirent 
+0

不,編寫的代碼使得模板替換對於指針的'max'失敗。你可以看到,如果你爲引用註釋掉'max'的定義:將會出現編譯錯誤。如果編譯錯誤是固定的,那麼總是選擇指針的'max',因爲3參數'max'中的類型是一個指針。 –