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

And*_*rew 5 c++ parameters portability scope namespaces

这看起来有点落后于我,但它有效:

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

Dav*_*eas 13

这是ADL(Argument Dependent Lookup)或Koenig Lookup(用于该功能的设计者).该功能的目的是在许多情况下,相同的命名空间将包含可应用于这些类型的类型和函数,所有类型和函数都符合接口.如果没有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 )
}
Run Code Online (Sandbox Code Playgroud)

虽然看起来像是一个尴尬的情况,但考虑n可能是std命名空间,test可能是ostream,并且operator+可能是operator<<:

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

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


Let*_*_Be 2

它被称为 Koenig 又名参数依赖查找http://en.wikipedia.org/wiki/Argument-dependent_name_lookup