【问题标题】:Unqualified name lookup finds inline namespace member非限定名称查找找到内联命名空间成员
【发布时间】:2014-08-05 08:52:13
【问题描述】:

我写了以下代码:

   #include <iostream>

    inline namespace M
    {
        int j=42;
    }

    int main(){ std::cout << j << "\n"; } //j is unqualified name here. 
                 //Hence, unqualified name lookup rules will be applied.
                 //This implies that member of inline namespace shall not be considered. 
                 //But it is not true

而且效果很好。但我预计该程序格式不正确。这是因为标准说(N3797,第 7.3.1/7 节):

最后,通过显式在封闭的命名空间中查找名称 资格(3.4.3.2)将包括内联命名空间的成员 由 using 指令引入,即使有声明 该名称位于封闭的命名空间中。

第 3.4.1/6 节也没有说明在非限定名称查找中涉及内联命名空间:

在函数的定义中使用的名称 declarator-id 28 是命名空间 N 的成员(其中,仅用于 说明的目的,N 可以代表全局范围)应为 在使用它之前在使用它的块中或在其中之一中声明 它的封闭块(6.3)或,应在其使用前声明 命名空间 N 或者,如果 N 是嵌套命名空间,则应在之前声明 它在 N 的封闭命名空间之一中使用。

这是 g++ 错误还是我理解错误的规则?

【问题讨论】:

    标签: c++ c++11 namespaces inline language-lawyer


    【解决方案1】:

    没有错误..

    不,这不是g++(或clang++)的错误,它具有所描述的行为,编译器应该找到j

    inline namespace N {
      int j;
    }
    
    int main () {
      int a = j; // legal, `j` == `N::j`
    }
    

    标准是怎么说的?

    您遗漏了标准的一个非常重要的部分,即 7.3.1§8,其中指出内联命名空间的封闭命名空间隐式具有 using 指令 引用内联命名空间。

    [7.3.1]p8 命名空间定义 [namespace.def]

    内联命名空间的成员在大多数情况下都可以使用,因为它们被认为是封闭命名空间的成员。具体来说,内联命名空间及其封闭命名空间都被添加到参数相关查找(3.4.2)中使用的关联命名空间集合中,只要其中一个是,a using-directive命名内联命名空间的 (7.3.4) 隐式插入到封闭的命名空间 中,就像未命名的命名空间 (7.3.1.1) 一样。


    细化

    这意味着我们之前的示例在语义上等价于下面的示例,其中我们引入了一个 using-directive 来将嵌套命名空间中的名称引入全局命名空间:

    inline namespace N {
      int j;
    }
    
    using namespace N; // the implicit using-directive    
    
    int main () {
      int a = j; // legal
    }
    

    【讨论】:

    • +1 TIL 隐式暴露了内联命名空间!
    猜你喜欢
    • 2015-04-11
    • 2019-08-28
    • 1970-01-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多