【问题标题】:What are the name resolution rules in C++ namespaces?C++ 命名空间中的名称解析规则是什么?
【发布时间】:2020-12-10 15:40:04
【问题描述】:

如何在 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”的引用不明确

这背后的逻辑是什么?

【问题讨论】:

    标签: c++ namespaces language-lawyer


    【解决方案1】:

    使用指令要记住的规则如下

    [namespace.udir]

    2 using-directive 指定提名中的名称 命名空间可以在 using 指令所在的范围内使用 出现在 using 指令之后。在不合格名称查找期间 ([basic.lookup.unqual]),名称看起来好像它们是在 最近的封闭命名空间,其中包含 using-directive 和指定的命名空间。 [注:在这种情况下, “包含”是指“直接或间接包含”。 ——尾注]

    3 using-directive 不向声明性添加任何成员 它出现的区域。

    第 3 段确保我们不会收到错误直到尝试名称查找。它没有添加声明,只要str 没有通过非限定名称查找进行查找,我们就不会发生冲突。而第 2 段告诉我们名称的逻辑布局。我们可以将其应用于您的两个示例。

    1. 包含using namespace ns1; 和命名空间ns1 本身的最近封闭命名空间是全局命名空间。所以ns1::str 这个名字就像我们写的一样

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

      因此,名称查找只会找到 ns2::str,因为它会隐藏任何 str 并封闭命名空间(这是上面代码中的“假设”情况)。

    2. 同样,最近的封闭命名空间是全局命名空间。但这一次,我们得到的布局不同

      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; }
      }
      

      显然,上面的“等效”代码 sn-p 不是有效的,声明将是相互冲突的。但这是冲突根源的例证。来自该范围的名称存在冲突。所以非限定名称查找失败。

    在没有使用指令的情况下,非限定名称查找的行为相当直观。范围从内到外查找,直到找到名称声明。

    【讨论】:

    • 哦,所以 using 指令不会将名称“放置”在它出现的命名空间中,而是放置在最里面的命名空间中,这是 using 指令和它正在使用的命名空间的共同祖先。我觉得这违反直觉,但现在一切都说得通了。感谢您的解释!
    猜你喜欢
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2020-10-28
    • 2010-12-02
    相关资源
    最近更新 更多