22

私はあなたの考慮のためにここに小さなコードを持っていますが、それは私をかなり困惑させます。奇妙なことに、Sun StudioとGCCの両方でコンパイルされますが、コンパイルされるべきではないと思います。

このことを考慮:

namespace name
{
  class C
    {
      int a;
    };

  void f(C c);
  void g(int a);
}

int main(int argc, char** argv)
{
  name::C c;

  name::f(c); 
  f(c);  // <--- this compiles, strangely enough

  name::g(42);
  // g(42);  <--- this does not, as I expected
}

同じ名前空間からのclass引数により、関数は名前空間fから「リーク」し、。なしでアクセスできるようになりますname::

誰かがこれについての説明がありますか?確かに私であり、コンパイラがここで間違っているわけではありません。

4

4 に答える 4

29

これは、引数依存のルックアップ(またはケーニッヒルックアップ)と呼ばれます。つまり、コンパイラは、引数タイプの名前空間である名前空間で関数を探します。

于 2011-02-03T13:10:19.657 に答える
12

これは、引数依存の名前ルックアップ、別名ADL、別名ケーニッヒルックアップです。これは、オペレーターが期待どおりに機能するようにするために考案されました。例:

namespace fu {
    struct bar { int i; };
    inline std::ostream& operator<<( std::ostream& o, const bar& b ) {
        return o << "fu::bar " << b.i;
    }
}

fu::bar b;
b.i = 42;
std::cout << b << std::endl; // works via ADL magic

ADLがない場合は、出力演算子を醜いものusing fu::operator<<;にするか、さらに醜い明示的な呼び出しを使用する必要があります。

fu::operator<<( std::cout, b ) << std::endl;
于 2011-02-03T13:13:03.090 に答える
7

これは「引数依存のルックアップ」によるものです。constを削除しても、表示されている動作は変わりません。それがADLであることを示すために、名前空間の外にSt構造体を移動してみてください...

struct St
{
   int a;
};

namespace name
{
  void f(const St& st);
  void g(int a);
}

int main(int argc, char** argv)
{
  St st;

  name::f(st); 
  f(st);  // <--- now you will get the expected compile error

  name::g(42);
  // g(42);  <--- this does not, as I expected
}
于 2011-02-03T13:17:06.523 に答える
1

これは、引数に依存するルックアップが原因です。

于 2011-02-03T13:18:37.363 に答える