7

を機能次のことを考えてみます。最初のケースで引数依存ルックアップが

namespace N { 
    struct A { }; 

    struct B { 
     B() { } 
     B(A const&) { } 
     friend void f(B const&) { } 
    }; 
} 

int main() { 
    f(N::B{}); // ok 
    f(N::A{}); // error 
} 

、ケースが成功する - 私たちはN::Bの関連する名前空間を考慮し、N::f(B const&)を見つけます。すばらしいです。

2番目のケースは失敗します。どうして? [namespace.memdef]によると:

非ローカルクラスでfriend宣言が最初のクラス、関数、クラステンプレートまたは関数テンプレートを宣言する場合友人は最も内側の名前空間のメンバーです。 [...]フレンド関数またはファンクションテンプレート が呼び出された場合、その名前は、ファンクション引数の型(3.4.2)に関連するネームスペースおよびクラスからファンクションを考慮する名前ルックアップによって検出されます。

N::Aの関連する名前空間はfがメンバーである、Nあるので、なぜそれが検索によって発見されていませんか?

答えて

8

fが関連付けられたクラスで宣言されていないためです。 Bは、引数の型がBの場合は関連付けられたクラスですが、引数の型がAの場合は関連付けられません。

Iは、[basic.lookup.argdep]/4から強調鉱山を引用:

関連付けられた名前空間を考慮すると、ルックアップが 関連付けられた名前空間は次のように使用されている場合に実行ルックアップと同じです

- 関連する名前空間の使用ディレクティブはすべて無視されます。

- 任意の名前空間スコープのフレンド関数またはフレンド関数テンプレート関連クラスで宣言されたが、彼らは通常のルックアップ(11.3)の間に表示されていない場合でも、それぞれの名前空間内に見える です。

- (過負荷の可能性がある)関数や関数テンプレート以外のすべての名前は無視されます。

関連する問題