为什么C ++参数范围会影响命名空间中的函数查找?

时间:2011-03-22 14:18:54

标签: c++ parameters namespaces scope portability

这对我来说似乎有些落后但是有效:

#include <iostream>

namespace nTest
{
  struct cTest {};

  void fTest(cTest& x)
  {
    std::cout << "nTest::fTest(cTest&) called" << std::endl;
  }
}

int main(void)
{
  nTest::cTest x;
  fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest.
  return 0;
}

通常,您需要nTest ::才能访问fTest,但其属于nTest的参数似乎将nTest添加到搜索fTest的可能范围列表中。我觉得参数范围影响函数查找似乎很奇怪。

这在GCC编译得很好,但我想知道这种用法是否可移植?该范围机制的官方定义是什么?

3 个答案:

答案 0 :(得分:13)

这是ADL(Argument Dependent Lookup)或Koenig Lookup(用于该功能的设计者)。该功能的目的是在许多情况下,相同的命名空间将包含可应用于这些类型的类型和函数,所有类型和函数都符合 interface 。如果没有ADL,则必须将标识符带入using声明的范围,否则您必须对调用进行限定。

这成为一场噩梦,因为语言允许操作员超载。请考虑以下示例:

namespace n {
   struct test {};
   test operator+( test, test const & ); // implemented
};
int main() {
   n::test a,b;
   n::test c = a + b;  //without ADL: c = n::operator+( a, b )
}

虽然看起来似乎很尴尬,但考虑n可能是std命名空间,test可能是ostream,而operator+可能是operator<<

int main( int argc, char** ) {
   std::cout << "Hi there, there are " << argc << " arguments" << std::endl;
}

如果没有ADL,对operator<<的调用必须是明确的,而且你必须知道哪些是作为自由函数而不是方法实现的。您是否知道std::cout << "Hi"正在调用自由函数而std::cout << 5正在调用成员函数?没有多少人意识到这一点,而且严肃地说,几乎没有人关心。 ADL隐藏了你。

答案 1 :(得分:3)

它被称为Koenig aka Argument dependent lookup http://en.wikipedia.org/wiki/Argument-dependent_name_lookup

答案 2 :(得分:1)

它最初设计用于查找重载运算符,如运算符&lt;&lt;你用来发送一个字符串到std :: cout。如果我们没有ADL,您将不得不编写这样的代码:std::operator<<(std::cout, "nTest::fTest(cTest&) called")

不太好!

如果它适用于运营商,为什么不以相同的方式运行功能呢?