[英]Wrong overloaded template function is called
我有以下帶有重載模板函數的代碼
#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;
}
我以為它會失敗,因為帶有三個參數的max模板將返回對臨時變量的引用(由模板返回的指針)。 但是它可以工作並調用常規模板函數。
問題是為什么不將指針稱為模板?
謝謝。
沒用 這似乎可行,因為您僅使用前兩個參數或三個參數的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
}
更正表明了正在發生的情況:您正在比較指針地址。
看到這里行動 。
不會調用指針重載,因為該引用版本更適合: a1
等是const引用(但指向指針)。 因此,參考版本在重載分辨率方面是完美匹配。
我想要實現您想要的功能,這里需要一些SFINAE魔術。
我想補充一件事:由於比較指針是C ++中的一項常用操作,恕我直言,在比較之前先對指針進行max
取消引用將是非常誤導的。
如果注釋掉2-argument 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;
}
如果注釋掉了指針模板的定義,則將調用引用模板。 由於類型已經是指針,因此似乎出現了指針模板優於引用模板的情況。
以下是有關模板匹配順序的一些解釋: 從重載模板函數中選擇的規則是什么?
編輯: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*
。
當你調用max(a, b, c)
T
的max(const T& a1, const T& a2, const T& a3)
成為一個別名int *
在最大(常量T&A1,常量T&A2,常量T&A3,所以) max(a,b)
將匹配max(const T& a1, const T& a2)
typedef int * T;
const T x;
const int * y; //they are different
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.