我一直在阅读 Bjarne Stroustrup 所著的《C++ 编程语言》中的命名空间章节,并对如何使用参数依赖查找来调用函数感到困惑。以下是书中的代码片段:
代码片段 1
namespace Chrono {
class Date { /* ... */ };
bool operator==(const Date&, const std::string&);
std::string format(const Date&); // make string representation
// ...
}
void f(Chrono::Date d, int i)
{
std::string s = format(d); // Chrono::format()
std::string t = format(i); // error: no format() in scope
}
这个片段对我来说很有意义,因为 Chrono 是函数 f 的参数中使用的命名空间,因此可以成功搜索 format(Date) 函数。函数 f 和命名空间 Chrono 似乎共享相同的范围,这让我对下一个片段感到困惑:
代码片段 2
namespace N {
struct S { int i };
void f(S);
void g(S);
void h(int);
}
struct Base {
void f(N::S);
};
struct D : Base {
void mf();
void g(N::S x)
{
f(x); // call Base::f()
mf(x); // call D::mf()
h(1); // error: no h(int) available
}
};
这对我来说是有意义的,直到“h(1);”行由于结构体和命名空间 N 共享相同的作用域,为什么在命名空间 N 中找不到函数“void h(int)”?
Stroustrup 确实接着说“如果参数是命名空间的成员,则关联的命名空间就是封闭的命名空间。”由于 g 的参数是命名空间 N 的成员,这是否意味着封闭的命名空间是不包含函数“h(int)”的全局命名空间?如果是这样的话,如果封闭的命名空间是也不包含“format(Date)”函数的全局命名空间,为什么 Snippet 1 不会失败?
预先感谢您对此事的深入了解!
最佳答案
ADL 应用基于调用本身的参数类型,而不是调用可能位于或不位于的函数的参数类型。
在 format(d)
中,在 Chrono
中查找 format
,因为该调用的参数 d
> 的类型为 Chrono::Date
,而 Chrono
是该类型的关联命名空间。包含调用的函数是 void f(Chrono::Date d, int i)
还是 void f()
无关紧要。 (显然,在后一种情况下,假设有一个 Chrono::Date d;
。)
关于c++ - 对 C++ 中的命名空间和参数相关查找感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37151092/