2012-08-08 104 views
9

在下面的C++代碼中,首先爲單個double參數定義foobar,然後再爲單個參數Foo類型定義一個參數。兩者都在全局命名空間內定義。從另一個命名空間訪問C++全局命名空間

one名稱空間內,定義了foobar的進一步重載,其中有Bar類型的單個參數。從foobar的這個版本中,帶double參數(42.0)的foobar的非限定調用將失敗。類似的調用foobar,這次用(::)作用域分辨率運算符進行限定,也有一個double的參數,但會成功。

另一方面,對foobar的非保留調用(具有類型Foo的參數)成功。調用foobar並使用Foo參數(由範圍解析運算符進行限定)也會成功。

爲什麼這兩種情況的行爲有所不同?我使用gcc 4.7和clang ++ 3.2。

struct Foo {}; 
struct Bar {}; 

double foobar(double x) { return x; } 
Foo foobar(Foo f) { return f; } 

namespace one { 

    Bar foobar(Bar b) { 
    //foobar(42.0); // error: can't convert to Bar 
    ::foobar(42.0); 

    Foo f; 
     foobar(f); // no problem 
    ::foobar(f); 
    return b; 
    } 
}; 

回答

8

Argument dependent lookup

在調用foobar(f)函數時,將考慮Foo的命名空間。

不適用於double,因爲該類型未在任何名稱空間中聲明。

+0

作爲最後一句的補充:非限定名稱查找只要找到匹配的*名稱就停止,首先考慮本地範圍,並且只有當它沒有找到任何名稱時,它纔會搜索上層和全局範圍。 – Xeo 2012-08-08 22:09:23

+0

謝謝博。與ADL的鏈接使事情變得清晰。 – user2023370 2012-08-08 22:18:39

+0

@Xeo:這是否意味着在找到foobar(Bar b)'後,調用foobar(f)'會失敗? – user2023370 2012-08-08 22:39:55