非限定名称查找查找内联命名空间成员

Unqualified name lookup finds inline namespace member

本文关键字:查找 命名空间 成员 定名称      更新时间:2023-10-16

我写了以下代码:

   #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, sec. 7.3.1/7):

最后,通过explicit在封闭命名空间中查找名称qualification(3.4.3.2)将包含内联命名空间的成员由using指令引入,即使有声明

第3.4.1/6节也没有提到在非限定名查找中涉及内联命名空间的任何内容:

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

这是一个g++错误还是我理解规则不正确?

没有问题。

不,这不是一个bug在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)中使用的关联命名空间集中,并且一个命名内联命名空间的using指令(7.3.4)被隐式地插入到封闭命名空间中,就像未命名命名空间(7.3.1.1)一样。


精化

这意味着我们前面的例子在语义上等同于下面的例子,其中我们引入了一个using指令,将嵌套命名空间中的名称引入全局命名空间:

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