2010-05-28 94 views
4

我試圖編譯這段代碼與GCC 4.5.0:奇怪超載規則

#include <algorithm> 
#include <vector> 

template <typename T> void sort(T, T) {} 

int main() 
{ 
    std::vector<int> v; 
    sort(v.begin(), v.end()); 
} 

但它似乎不工作:

$ g++ -c nm.cpp 
nm.cpp: In function ‘int main()’: 
nm.cpp:9:28: error: call of overloaded ‘sort(std::vector<int>::iterator, std::vector<int>::iterator)’ is ambiguous 
nm.cpp:4:28: note: candidates are: void sort(T, T) [with T = __gnu_cxx::__normal_iterator<int*, std::vector<int> >] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/stl_algo.h:5199:69: note:     void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >] 

科莫編譯此代碼,而無需錯誤。 (4.3.10.1 Beta2,strict C++ 03,no C++ 0x)

這個有效的C++嗎?

爲什麼海灣合作委員會甚至將std::sort視爲一個有效的超載?


我做了一些實驗,我想我知道爲什麼科莫可能編譯這個(但我不知道這是事實):

namespace foo { 
typedef int* iterator_a; 
class  iterator_b {}; 
template <typename T> void bar(T) {} 
} 

template <typename T> void bar(T) {} 

int main() 
{ 
    bar(foo::iterator_a()); // this compiles 
    bar(foo::iterator_b()); // this doesn't 
} 

我的猜測是,第一個電話解析爲bar(int*),所以沒有ADL並且沒有歧義,而第二個電話解析爲bar(foo::iterator_b)並且拉入foo::bar(但我不太確定)。

所以GCC可能使用類似iterator_b而科莫使用iterator_a

+0

我發現科莫行爲怪異,這意味着他們的'iterator'不住在'std'命名空間還是我失去了一些東西? – 2010-05-28 08:16:29

+0

我用一些可以玩的代碼更新了答案。 – bucels 2010-05-28 08:45:49

回答

8

可以明確完全限定名稱作爲::sort指定sort功能。

模棱兩可的過載是由於argument dependent lookup。 C++標準沒有指定應該如何實現std::vector<*>::iterator。 gcc的庫作家都選擇使用模板(__gnu_cxx::__normal_iterator)與std::vector模板類型參數,它帶來的命名空間std到相關的命名空間的列表。


這是合法的C++?

是的,但兩者的編譯器的行爲也符合C++標準。從這個角度來看,ADL呈現出令人頭痛的問題,直到標準化之後才能理解全部後果。