2013-05-28 31 views
0

我對下面的代碼有疑問。當我編譯它時抱怨下面有這個錯誤。現在我的問題是,如果我刪除了「常量」,在聲明中,更改爲只:使用模板時C++「const」神祕重載函數調用

template<class T> T max(T& left, T& right); 

變得好和編譯/正確執行。編譯器如何認爲該調用是模糊的?前向聲明不應該遵循實現嗎?

==== start of error message==== 
max.cpp:10:34: error: call of overloaded ‘max(int, int)’ is ambiguous 
max.cpp:10:34: note: candidates are: 
max.cpp:5:21: note: T max(const T&, const T&) [with T = int] 
/usr/include/c++/4.6/bits/stl_algobase.h:210:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int] 
max.cpp:11:44: error: call of overloaded ‘max(double, double)’ is ambiguous 
max.cpp:11:44: note: candidates are: 
max.cpp:5:21: note: T max(const T&, const T&) [with T = double] 

=======end of error message=== 

=============代碼從這裏開始======

#include<iostream> 

using namespace std; 

template<class T> T max(const T& left, const T& right); 

int main(void) 
{ 

     cout<<"max int:"<< max(1,4)<<endl; 
     cout<<"max double:"<< max(5.02,1.002)<<endl; 

} 

template<class T> 
T max(const T& left, const T& right) 
{ 

     return left > right? left:right; 
} 
+8

'using namespace std;'的另一種情況...... –

回答

5

你要做的:

cout<<"max int:"<< ::max(1,4)<<endl; 
    cout<<"max double:"<< ::max(5.02,1.002)<<endl; 

由於是std命名空間中定義的另一個max。您必須通知編譯器使用在您定義的全局名稱空間中定義的max。看到這裏一個活生生的例子:Function template Demo

如果你看一下在std名字空間中定義的std::max

template <class T> const T& max (const T& a, const T& b); 

返回const引用,並採取常量引用參數,這就是爲什麼當您刪除常量,它會編譯。希望這有助於。

+0

所以你說的是我的聲明和std命名空間中的聲明是衝突的嗎?這是因爲我的聲明與std中的參數具有相同的參數,但返回類型不同(僅限於const T&vs T)。我是否正確理解問題? – dean

+0

@dean是的,正確的 – taocp

0

std命名空間已經內置了一個最大值,所以你可以沒有using namespace std;行,或者把max函數放在你自己的命名空間中。

namespace myNamespace { 
    //your max function 
} 
+0

或在'max'之前使用範圍解析運算符''::''來查看全局範圍,如其他答案中所述。即'':: max'' –

0

我們在std命名空間(如max(),swap()qsort())中已經定義了很少的函數。所以當你定義你自己的功能時

max(const T& left,const T& right) 

它和std命名空間中的一樣,因此是錯誤。所以你可以做以下,使工作

  1. 使用範圍解析操作::最大調用你的函數(X,Y)

  2. 從你的函數刪除const修飾

0

正如其他人所寫的,編譯器已經在命名空間標準中另外發現了一個最大函數。現在它試圖通過函數重載爲你獲得最好的版本。由於兩個簽名都是平等的,因此無法選擇最佳版本並投訴。現在,如果你刪除了const,編譯器就不能將一個整數(或雙精度)的字面值綁定到一個非常量參考。現在它只有一個選擇,並採用std :: max功能。你可以用下面的例子看看吧:

#include <iostream> 

namespace ns1 { 

    template<class T> 
    void doit(T const&) { 
     std::cout << "ns1::doit" << std::endl; 
    } 
} 

template<class T> 
void doit(T&) { 
    std::cout << "::doit" << std::endl; 
} 

int main() { 
    using namespace ns1; 
    int i=1; 
    int const j=1; 
    doit(1); 
    doit(i); 
    doit(i+1-1); 
    doit(j); 
    return 0; 
} 

由於everithing是int,編譯器有選擇,只有當它有一個非const的變量(i)非const引用。在其他情況下,它從命名空間ns1中選擇cont參考版本。它甚至可以將臨時對象綁定到常量引用(i + 1-1)。這與max和std :: max一樣。

編輯

我forgott如果去掉常量在聲明中,編譯器說選擇的std ::最大這當然是正確的,但不是你的。