C++命名空间中的名称解析规则是什么?

3

C++命名空间中名称是如何解析的?

我特别关注在多种不同方式下提供名称的情况,例如由父命名空间和using namespace提供。

看下面这段代码:

namespace ns1 {
    static auto str = "ns1::str";
}
namespace ns2 {
    static auto str = "ns2::str";
    namespace sub {
        using namespace ns1;
        auto f() { return str; }
    }
}

使用我的编译器,ns2::sub::f() 返回值是"ns2::str"。我预期它应该返回"ns1::str",因为using namespace ns1出现在ns2::sub中。

下面是另一个示例:

static auto str = "str";
namespace ns1 {
    static auto str = "ns1::str";
}
namespace ns2 {
    using namespace ns1;
    auto f() { return str; }
}

我原以为它会像之前那样表现,但实际上它无法编译:

错误:对‘str’的引用不明确

这是什么逻辑呢?
1个回答

2
使用指令需要记住以下规则:

[namespace.udir]

2 使用指令指定被提名命名空间中的名称可以在使用指令出现后的范围内使用。在未限定名称查找([basic.lookup.unqual])期间,这些名称看起来就像是声明在最近的封闭命名空间中,该命名空间包含使用指令和被提名的命名空间。[注意:在此上下文中,“包含”意味着“直接或间接包含”。—注]

3 使用指令不会向其所在的声明区域添加任何成员。

第三段确保我们在尝试名称查找之前不会出现错误。它不添加声明,只要没有通过未限定名称查找查找到“str”,我们就不会出现冲突。而第二段告诉我们名称的逻辑布局方式。我们可以将其应用于您的两个示例。
  1. The nearest enclosing namespace that contains both the using namespace ns1; and the namespace ns1 itself is the global namespace. So the name ns1::str behaves as if we had written

    static auto str = "ns1::str";
    namespace ns2 {
       static auto str = "ns2::str";
        namespace sub {
            auto f() { return str; }
        }
    }
    

    So, name lookup would only find ns2::str, because it would hide any str from and enclosing namespace (which is the "as-if" situation in the code above).

  2. Again, the nearest enclosing namespace is the global one. But this time, the layout we get is different

    static auto str = "str"; // This is the one declared
    static auto str = "ns1::str"; // This is the one "as-if" made available
    
    namespace ns2 {
        auto f() { return str; }
    }
    

    Obviously, the above "equivalent" code snippet isn't a valid one, the declarations would be conflicting ones. But it is an illustration to the source of the conflict. The name coming from that scope is in conflict. So unqualified name lookup fails.

在没有使用指令的情况下,未限定名称查找的行为相当直观。作用域从内向外查找,直到找到名称的声明为止。

哦,所以using指令并不是将名称放置在它出现的命名空间中,而是放置在最内层的命名空间中,该命名空间是使用using指令和命名空间的共同祖先。我觉得这很反直觉,但现在一切都讲得通了。谢谢你解释这个问题! - Helloer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接