3

Josuttis テンプレート ブックを読んでいて、ADL について頭を悩ませようとしています。彼は、「ADL は、呼び出し引数の型に「関連付けられた」名前空間とクラスで名前を検索することによって処理を進める」と述べています。クラスで名前を検索する方法を確認しようとしています。以下に私のテストの例を示します。名前空間で名前を検索する方法がわかります。

class bryan_ns {
  public:
  class bryan {
    public:
      enum E { e1 };
      static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  };

  void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

void f(int)
{
  std::cout << "::f(int) called\n";
}


int main()
{
  f(bryan_ns::bryan::e1); // calls ::f(int)
}

しかし、bryan_ns を名前空間に次のように変更すると:

namespace bryan_ns {
  public:
  class bryan {
    public:
      enum E { e1 };
      static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
  };

  void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

void f(int)
{
  std::cout << "::f(int) called\n";
}


int main()
{
  f(bryan_ns::bryan::e1); // calls bryan_ns::f(bryan::E)
}
4

2 に答える 2

7

ADL は、型を囲んでいる名前空間だけでなく、型自体の内部も調べます。最良の例は、型内で定義されているフレンド関数です。

namespace X {
class test {
   friend void f( test ) { std::cout << "test" << std::endl; }
};
}
int main() {
   X::test t;
   f( t );
}

への呼び出しは、 type 内でのみ使用可能な宣言f(t)を見つけます。これは、フレンド関数宣言のあまり知られていない機能です。名前空間レベルの関数を宣言しますが、型内でのみ宣言を提供します。この動作を確認する簡単なテスト:X::ftest

namespace X {
   class test {
      friend void f( test );
   };
   //void f( test );          // [1]
}
void X::f( X::test ) {}       // [2]
int main() {
   X::test t;
   f(t);                      // [3]
}

[2]の定義は、既に宣言されている関数しか定義できないため、コンパイル エラーを引き起こします。 [2] は名前空間の外にあるため、Xその定義は自己宣言の目的を果たしません (定義した場合)。存在する名前空間内の関数の場合、定義は宣言でもありますが、この場合はそうではありません)。[1] のコメントを外すと、エラーはなくなります。または、[2] にコメントを付けると、[3] の呼び出しで、ADL がクラス内で宣言を見つけたことを示すコードがコンパイルされます。

于 2012-07-13T02:54:09.580 に答える
0

最初の例でbryan_ns::fは、非静的メンバー関数です。の式にmain.or->メンバー演算子がないため、明らかにメンバー関数呼び出しでbryan_ns::fはなく、実行可能な関数ではありません。

于 2012-07-13T00:18:22.067 に答える