对 C++ 中的名称空间和参数相关查找感到困惑

Confused about namespaces and Argument-Dependent Lookup in C++

我一直在通读 Bjarne Stroustrup 撰写的 The C++ Programming Language 中的名称空间章节,并对如何使用参数相关查找调用函数感到困惑。以下是书中的代码片段:

片段 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 继续说 "If an argument is a member of a namespace, the associated namespaces are the enclosing namespaces." 因为 g 的参数是命名空间 N 的成员,这是否意味着封闭的命名空间是不包含函数的全局命名空间 "h(int)" ?如果是这样的话,如果封闭的命名空间是也不包含 "format(Date)" 函数的全局命名空间,为什么代码段 1 不会失败?

在此先感谢您对此事的深入了解!

ADL 的应用基于调用本身的参数类型,而不是调用可能在也可能不在的函数的参数类型。

format(d) 中,formatChrono 中查找,因为该调用的参数 d 属于 Chrono::Date 类型,并且Chrono 是该类型的关联命名空间。包含调用的函数是 void f(Chrono::Date d, int i) 还是 void f() 无关紧要。 (显然,在后一种情况下,假设有一个 Chrono::Date d;。)