我一直在阅读 Josuttis 模板书,并且我一直试图将我的头放在 ADL 上。他说“ADL 通过在命名空间和类中查找名称与调用参数的类型“关联”来进行。我只是想看看它是如何在类中查找名称的。我在下面举了一个我的测试示例。我看到它如何在命名空间中查找名称。
class bryan_ns {
public:
class bryan {
public:
enum E { e1 };
static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
void f(int)
{
std::cout << "::f(int) called\n";
}
int main()
{
f(bryan_ns::bryan::e1); // calls ::f(int)
}
但是,如果我将 bryan_ns 更改为这样的命名空间:
namespace bryan_ns {
public:
class bryan {
public:
enum E { e1 };
static void bryan_test() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
void f(bryan::E) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
void f(int)
{
std::cout << "::f(int) called\n";
}
int main()
{
f(bryan_ns::bryan::e1); // calls bryan_ns::f(bryan::E)
}
最佳答案
ADL 将查看类型的封闭命名空间以及类型本身。最好的例子是在类型内部定义的友元函数:
namespace X {
class test {
friend void f( test ) { std::cout << "test" << std::endl; }
};
}
int main() {
X::test t;
f( t );
}
对
f(t)
的调用将找到 X::f
,其声明仅在 test
类型内可用。这是友元函数声明的一个鲜为人知的特性:它们声明了一个命名空间级别的函数,但只在类型内部提供声明。验证此行为的简单测试:namespace X {
class test {
friend void f( test );
};
//void f( test ); // [1]
}
void X::f( X::test ) {} // [2]
int main() {
X::test t;
f(t); // [3]
}
[2] 中的定义将触发编译错误,因为您只能定义一个已经声明的函数,并且由于 [2] 在 namespace
X
之外,该定义不用于自我声明的目的(如果您在它所在的命名空间内定义一个函数,那么该定义也是一个声明,但在这种情况下不是)。如果我们取消注释 [1],错误就会消失。或者,如果我们注释 [2],则代码将编译,表明对于 [3] 中的调用,ADL 已在类中找到了声明。关于c++ - 参数相关查找是否也只搜索 namespace 或类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11462474/