具有类参数的函数是否从命名空间泄露?

lyt*_*nyn 22 c++ namespaces argument-dependent-lookup

我在这里有一小段代码供您考虑,这让我感到非常困惑.奇怪的是,它在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
}
Run Code Online (Sandbox Code Playgroud)

来自同一命名空间的类参数会导致函数f"泄漏"到命名空间之外,并且无需访问name::.

有人对此有解释吗?这当然是我而不是编译器在这里错了.

Tim*_*tin 29

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

  • @lytenyn:这是你每天都使用的:)`std :: string s; s + ="aa";`,这里`+ =`来自`std`命名空间,即使你从未指定它,多亏了ADL. (5认同)

Nik*_*sov 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
Run Code Online (Sandbox Code Playgroud)

如果没有ADL,你必须明确地使输出操作符变得丑陋using fu::operator<<;,或者使用更加丑陋的显式调用:

fu::operator<<( std::cout, b ) << std::endl;
Run Code Online (Sandbox Code Playgroud)

  • 这篇文章非常简短,你的好奇心在哪里? (2认同)

dgn*_*ton 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
}
Run Code Online (Sandbox Code Playgroud)