4

まず第一に、この質問は純粋に理論的な性質のものです。私は解決策を探しているのではなく (既に知っています)、説明を探しているだけです。

次のコードはコンパイルされません。

struct foo {};
void a(foo) {}
namespace foobar {
    void a(foo) {}
    void b(foo f) {a(f);}
}
int main() {return 1;}

MSVC++:

1>c:\projects\codetests\main.cpp(7) : error C2668: 'foobar::a' : ambiguous call to overloaded function
1>        c:\projects\codetests\main.cpp(4): could be 'void foobar::a(foo)'
1>        c:\projects\codetests\main.cpp(2): or       'void a(foo)' [found using argument-dependent lookup]
1>        while trying to match the argument list '(foo)'

G++:

main.cpp: In function 'void foobar::b(foo)':
main.cpp:5:20: error: call of overloaded 'a(foo&)' is ambiguous
main.cpp:5:20: note: candidates are:
main.cpp:4:7: note: void foobar::a(foo)
main.cpp:2:6: note: void a(foo)

このコードのコンパイル中 (MSVC++ および G++):

namespace bar {struct foo {};}
void a(bar::foo) {}
namespace foobar {
    void a(bar::foo) {}
    void b(bar::foo f) {a(f);}
}
int main() {return 1;}

何故ですか?ここで、コンパイラの foo の周りの名前空間は何を変更しますか? この動作は C++ 標準で定義されていますか? 他の説明はありますか?ありがとう。

4

2 に答える 2

4

'void a(foo)' [引数依存ルックアップを使用して発見]

驚くべきことに、MSVC には非常に適切なエラーの説明があります。

標準に従って、コンパイラは関数内で、現在の名前空間と引数の型が定義されている名前空間でシンボルを探します。

最初のケースaではfoobar、引数 type の名前空間内にありfoo、グローバル名前空間であるため、あいまいになります。

2 番目のケースaでは、 is はfoobar引数 type の名前空間にありませんbar::foo: with isbarです。

于 2013-04-12T10:47:08.967 に答える
0

2 つのシンボル a(foo) があり、コンパイラはどちらを使用するかを決定できません。したがって、コンパイラに明示的に指示する必要があります。

foob​​ar の a(foo) を呼び出したい場合は、これを試してください。

   void b(foo f) { foobar::a(f); }

グローバルな a(foo) が必要な場合は、これを試してください。

   void b(foo f) { ::a(f); }
于 2013-04-12T10:42:59.263 に答える