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
}

来自同一命名空间的类参数会导致函数f“泄漏”出命名空间,并且可以在没有name::.

有人对此有解释吗?肯定是我,而不是编译器在这里出错。

4

4 回答 4

29

它被称为参数相关查找(或 Koenig 查找)。简而言之,编译器将在作为参数类型命名空间的命名空间中查找函数。

于 2011-02-03T13:10:19.657 回答
12

这是Argument-Dependent Name Lookup,又名 ADL,又名 Koenig 查找。这是为了使操作员按预期工作而发明的,例如:

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 回答