2014-03-01 104 views
1

這是關於C++中默認全局命名空間的問題。我有以下代碼編譯並使用g ++ clang-500.2.79正確運行。在全局命名空間中默認包含equal()嗎?

#include <string> 
#include <iostream> 

using std::string; 
using std::endl; 
using std::cout; 

bool is_palindrome(const string& str){ 
    return equal(str.begin(), str.end(), str.rbegin()); 
} 

int main(){ 

    cout << "Hello is a palindrome: " << is_palindrome("Hello") << endl; 
    cout << "madam is a palindrome: " << is_palindrome("madam") << endl; 

    return 0; 
} 

我的問題是,爲什麼這段代碼編譯正確?我忘記在我的文件的開頭放置#include <algorithm>using std::equal。所以預期的行爲是編譯器抱怨。

http://en.cppreference.com/w/cpp/algorithm/equal的示例證實我應該使用std::equal

爲了進一步調查,我試圖跟蹤,正好是哪個版本的equal()函數被調用。作爲C++的相對新手,我不知道如何做到這一點。我試過了,

cout << "The function is: " << equal << endl; 

與一些有趣的信息生成一個編譯器錯誤:

/usr/include/c++/4.2.1/bits/stl_algobase.h:771:5: 
note: 'std::equal' declared here 

嘗試,因爲我可能,我不能找到stl_algobase(或信息更可能的,我最有可能的別不明白我發現了什麼)。 stl_algobase是一組自動包含在全局命名空間中的函數嗎?

還有一個問題是:在C++中處理潛在的重載或模板函數時,跟蹤(代碼或其他)哪個函數被調用的正確方法是什麼?

回答

5

equal位於std命名空間中。你所看到的是argument dependent lookup(ADL)。由於參數位於std中,所以equal的名稱查找也會考慮該名稱空間。

這裏有一個簡單的例子:

namespace foo 
{ 
    struct Bar {}; 
} 

namespace foo 
{ 
    void bar(const Bar&) {} 
    void bar(int) {} 
} 

int main() 
{ 
    foo::Bar b; 
    foo::bar(b); // OK 
    bar(b);  // ADL, OK 
    foo::bar(42); // OK 
    bar(42);  // No ADL: error: 'bar' was not declared in this scope 
} 
+0

啊哈!但我想對於這樣的簡單情況,不應該依賴ADL。在使用ADL時,有沒有辦法讓編譯器*警告*? –

+1

@WilliamDenman我不確定你的意思是「不應該依賴」。它是語言的重要組成部分,沒有它,許多運算符重載將無法工作。編譯器沒有什麼可警告的。如果由於ADL你有一個模糊的過載,你會得到一個錯誤。 – juanchopanza

+0

完美。因此,在你的例子中,因爲struct Bar是在foo命名空間中定義的,但int不是,調用bar(b)可以找到void bar(const Bar&)函數,但是調用bar(42)找不到void bar (int) –