2012-08-08 29 views
9

以下のC++コードでは、doubleパラメータの場合はfoobarが最初に定義され、次にFooの場合は1つのパラメータとして再度定義されます。両方ともグローバル名前空間内で定義されています。別の名前空間内からのC++グローバル名前空間アクセス

one名前空間内には、さらにfoobarのオーバーロードが定義されており、単一のパラメータはBarです。このバージョンのfoobarでは、foobarへのdouble引数(42.0)の非修飾呼び出しは失敗します。 foobarへの同様の呼び出しは、今度はdouble引数を持つ(::)スコープ解決演算子で修飾されていますが、成功します。

一方、タイプFoofoobarへの非修飾呼び出しは成功します。スコープ解決演算子によって修飾されたのFoo引数の呼び出しも成功します。

なぜ2つのシナリオが異なる動作をするのですか?私は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

Fooという名前空間からの関数foobar(f)の関数を呼び出します。

doubleで動作しません。その型は任意の名前空間で宣言されていないためです。

+0

最後の文に加えて:修飾されていない名前の検索は、一致する* name *が見つかるとすぐに停止します。ローカルのスコープを考慮し、そこに名前が見つからない場合のみ、上位スコープとグローバルスコープを検索します。 – Xeo

+0

ありがとうございました。 ADLへのリンクは事を明確にします。 – user2023370

+0

@ Xeo:これは、 'foobar(f)'への呼び出しが 'foobar(Bar b)'を見つけて失敗することを意味しないでしょうか? – user2023370