参数依赖查找

在没有显式名称空间限定符的情况下调用函数时,如果该函数的某个参数类型也在该名称空间中,则编译器可以选择在名称空间中调用函数。这称为 Argument Dependent Lookup 或 ADL:

namespace Test
{
  int call(int i);

  class SomeClass {...};

  int call_too(const SomeClass &data);
}

call(5); //Fails. Not a qualified function name.

Test::SomeClass data;

call_too(data); //Succeeds

call 失败,因为它的参数类型都不是来自 Test 名称空间。call_too 有效,因为 SomeClassTest 的成员,因此它符合 ADL 规则。

什么时候不发生 ADL

如果正常的非限定查找找到类成员,已在块作用域声明的函数或不属于函数类型的函数,则不会发生 ADL。例如:

void foo();
namespace N {
    struct X {};
    void foo(X ) { std::cout << '1'; }
    void qux(X ) { std::cout << '2'; }
}

struct C {
    void foo() {}
    void bar() {
        foo(N::X{}); // error: ADL is disabled and C::foo() takes no arguments
    }
};

void bar() {
    extern void foo(); // redeclares ::foo
    foo(N::X{});       // error: ADL is disabled and ::foo() doesn't take any arguments
}

int qux;

void baz() {
    qux(N::X{}); // error: variable declaration disables ADL for "qux"
}