CPPreference提到"在确定命名空间与类的关联集合后,为了进一步的 ADL 处理,忽略此集中所有在类中找到的声明,但不包括命名空间作用域的友元函数及函数模板,在后述点 2 陈述。",如何理解在类中找到的声明,真的存在能在类中找到的声明吗,它的搜索范围包括类的内部吗,能否给出相应代码辅助理解?
时间: 2024-03-17 12:40:41 浏览: 121
在这里,“在类中找到的声明”是指在类内部声明的成员函数、成员变量、嵌套类型等。例如:
```
class A {
public:
void foo() {}
};
void bar(A a) {
a.foo(); // 这里的 foo 是在类内部声明的
}
```
在这个例子中,函数 `bar` 调用了 `A` 类的成员函数 `foo`,虽然 `foo` 函数在 `bar` 函数所在的命名空间中无法找到,但是根据 ADL 的规则,编译器会在 `A` 类所在的命名空间中查找与参数类型相关的函数,因此可以找到 `foo` 函数。
在实际编译中,编译器会在查找 ADL 候选函数时忽略类内部声明的函数。这是因为类内部声明的函数在编译时还没有定义,编译器无法确定它们是否满足 ADL 的要求。因此,在进行 ADL 查找时,编译器会直接忽略类内部声明的函数。
以下是一个简单的例子,说明类内部声明的函数不会被纳入 ADL 的搜索范围:
```
namespace ns {
struct A {
void foo() {}
};
void bar(A a) {
a.foo(); // 编译通过,能够找到 ns::foo 函数
}
void foo(A a) {}
}
int main() {
ns::A a;
ns::foo(a); // 编译错误,找不到 ns::foo 函数
return 0;
}
```
在这个例子中,`A` 类内部声明了成员函数 `foo`,`ns` 命名空间中也定义了一个函数 `foo`。在调用 `ns::foo` 函数时,编译器会查找与参数类型相关的函数,在这里是 `A` 类型的参数。由于类内部声明的函数不会被纳入 ADL 的搜索范围,因此编译器无法找到 `ns::foo` 函数,导致编译错误。
需要注意的是,类内部声明的友元函数和函数模板不会被忽略,它们可以被纳入 ADL 的搜索范围。例如:
```
namespace ns {
struct A {
template <typename T>
void foo(T t) {}
};
void bar(A a) {
a.foo(1); // 编译通过,能够找到 ns::foo 函数模板
}
template <typename T>
void foo(A a, T t) {}
}
int main() {
ns::A a;
ns::foo(a, 1); // 编译错误,找不到 ns::foo 函数模板
return 0;
}
```
在这个例子中,`A` 类内部声明了一个函数模板 `foo`,`ns` 命名空间中也定义了一个函数模板 `foo`。在调用 `ns::foo` 函数模板时,编译器会查找与参数类型相关的函数模板,在这里是 `A` 类型的参数和 `int` 类型的参数。由于类内部声明的函数模板会被纳入 ADL 的搜索范围,因此编译器能够找到 `ns::foo` 函数模板,编译通过。
阅读全文