0

以下のウィキペディアの記事では、引用が言及されています:

ADL は、非修飾名の通常の検索で一致するクラス メンバー関数が見つからない場合にのみ発生します。この場合、通常のルックアップでは考慮されない他の名前空間 が検索される可能性があります。検索される名前空間のセットは、関数の引数の型によって異なります

したがって、以下のプログラムが正常にコンパイルされることを期待していましたが、そうではありません

namespace N1 {
  class A {}; 
  void foo (A *p) {}
}
namespace N2 {
  void foo (N1::A &p) {}
}

int main () {
  N1::A xa; 
  foo(&xa); // ok
  foo(xa);  // error: cannot convert ‘N1::A’ to ‘N1::A*’ for argument ‘1’ to ‘void N1::foo(N1::A*)’
}

SO でいくつかの質問を検索しましたが、要件や状況を簡単な言葉で表したものを見つけることができませんでした。
もう少し詳細な回答は、私と将来の訪問者にとって本当に役に立ちます。

4

5 に答える 5

4

コンパイルされるべきではありません。A名前空間にありますN1。コンパイラは、あなたが呼び出したいことをどのように知る必要がありますN2::fooか? n3376 3.4.2/2

関数呼び出しの引数の型 T ごとに、0 個以上の関連付けられた名前空間のセットと、考慮される 0 個以上の関連付けられたクラスのセットがあります。名前空間とクラスのセットは、関数の引数の型 (およびテンプレート テンプレート引数の名前空間) によって完全に決定されます。 型を指定するために使用される typedef 名と using 宣言は、このセットには寄与しません。名前空間とクラスのセットは、次の方法で決定されます。

T がクラス型 (共用体を含む) の場合、関連するクラスは次のとおりです。 クラス自体。もしあれば、それがメンバーであるクラス。およびその直接および間接基本クラス。関連する名前空間は、関連するクラスがメンバーになっている名前空間です。さらに、T がクラス テンプレートの特殊化である場合、それに関連付けられた名前空間とクラスには次のものが含まれます。テンプレート テンプレート引数がメンバーである名前空間。テンプレート テンプレート引数として使用されるメンバー テンプレートがメンバーであるクラス。[ 注: 非型テンプレート引数は、関連付けられた名前空間のセットには寄与しません。— エンドノート]

于 2013-02-22T08:37:08.457 に答える
1

「他の名前空間」が検索されると表示されます。「すべての名前空間」が検索されるとは言いません。

ADL に含まれる追加の名前空間のルールは少し複雑ですが、最も重要なのはAが定義されている名前空間です。それがあなたの最初fooが見つかる理由です。名前空間は何の関係もなく、ADL によって検索されないため、 2 番目fooは見つかりません。N2

于 2013-02-22T08:41:51.403 に答える
1

修飾されていない名前のルックアップが失敗した場合、関数の呼び出しの引数を使用してルックアップが続行されます。

func(A x);

次に、コンパイラは、クラス A を含む名前空間から始まる名前空間を調べます。1 つの例は次のとおりです。

// argument_dependent_name_koenig_lookup_on_functions.cpp
namespace A
{
   struct X
   {
   };
   void f(const X&)
   {
   }
}
int main()
{
// The compiler finds A::f() in namespace A, which is where 
// the type of argument x is defined. The type of x is A::X.
   A::X x;
   f(x);   
}

詳細はこちら http://msdn.microsoft.com/en-us/library/60bx1ys7.aspx

于 2014-05-02T11:01:57.347 に答える
1

ADL は、関数がユーザーにユーザー定義型を渡すとすぐに、ほぼ常に起動します。ここで開始されfooます:xaは で定義されているN1ため、グローバル名前空間だけでなくfooで検索されます。N1(ADL をfoo使用しないと、グローバル名前空間でのみ検索されます。)

fooそして、2 番目の呼び出しがコンパイルされることを期待する理由がわかりません。の型はxaで定義されてN1いるため、ADL はN1検索パスに追加しますが、式には を意味するものは何もありませんN2

于 2013-02-22T08:41:17.653 に答える
0

一致する名前を持つ関数が見つかると、コンパイラは検索を停止します。引数の型またはアクセシビリティ (public/protected/private) が実際に現在のコンテキストで関数を使用できない場合、検索は続行されません。したがって、あなたの例では、が最初に見つかったため、コンパイラは "see"N2::fooに変更を加えていません。N1::foo

N2::fooあなたの例では、 が存在しなくても見つからないことに注意してください。内部のどこにもN1::foo参照がないため、まったく検索されません。N2mainN2

于 2013-02-22T08:41:23.853 に答える