簡體   English   中英

錯誤的重載模板函數被調用

[英]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) Tmax(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM