【发布时间】:2015-10-20 13:58:03
【问题描述】:
c++中有两种名称隐藏方式:
1) 普通名称隐藏:[basic.scope.hiding]p1 (http://eel.is/c++draft/basic.scope.hiding#1):
一个名字可以被一个同名的显式声明隐藏在一个 嵌套的声明区域或派生类 ([class.member.lookup])。
2) [basic.scope.hiding]p2 (http://eel.is/c++draft/basic.scope.hiding#2) 中隐藏的特殊名称类型:
类名([class.name])或枚举名([dcl.enum])可以是 被变量、数据成员、函数或枚举器的名称隐藏 在同一范围内声明。如果一个类或枚举名称和一个 变量、数据成员、函数或枚举器在 具有相同名称、类或枚举的相同范围(以任何顺序) name 隐藏在变量、数据成员、函数或 枚举器名称可见。
我很想知道在执行非限定名称查找时名称隐藏如何与 using 指令交互。
对于第一种类型的名称隐藏行为是非常清楚的。这是因为 [basic.scope.hiding]p1 已根据 [basic.lookup.unqual] (http://eel.is/c++draft/basic.lookup.unqual) 部分中的规则重新制定
第二种类型的名称隐藏没有这样做。所以现在出现了以下问题:
*) 第二种类型的名称隐藏应如何与涉及 using 指令的非限定名称查找交互?
在标准的其他地方我发现 [namespace.udir]p2 (http://eel.is/c++draft/namespace.udir#2) 我认为这是回答这个问题的关键:
using 指令指定指定命名空间中的名称 可以在 using 指令出现的范围内使用 使用指令。在不合格名称查找期间 ([basic.lookup.unqual]),名称出现就好像它们是在中声明的 最近的封闭命名空间,其中包含 using-directive 和指定的命名空间。 [注:在这种情况下, “包含”是指“直接或间接包含”。 ——尾注]
将此规则的 as if 部分应用于 [basic.scope.hiding]p1 可以与 [basic.lookup.unqual] 部分中的规则保持一致。此应用程序也与 [basic.scope.hiding]p4 (http://eel.is/c++draft/basic.scope.hiding#4) 一致,因此看起来很有希望。
因此,我认为我们可以通过类似地将 [namespace.udir]p2 的 as if 部分应用于 [basic.scope.hiding]p2 来回答问题 *)。此应用程序也与 [basic.scope.hiding] p4 一致。我认为这也是对c++标准最自然、最简单的解释。
但问题是 Clang 和 GCC 的解释与我不同。例如:
namespace N { static int i = 1; }
namespace M { struct i {}; }
using namespace M;
using namespace N;
int main() { sizeof(i); }
根据我的解释,这个程序应该是格式良好的,i 应该被查找为整数变量。 Clang 和 GCC 都不同意这一点,因为它给出了名称查找歧义。
对于 Clang,这种更复杂的解释会导致以下错误:
namespace N { static int i = 1; }
namespace M { struct i {}; }
namespace P {
using N::i;
using M::i;
}
namespace Q { using M::i; }
using namespace P;
using namespace Q;
int main() { sizeof (i); }
没有错误,但会改变
using namespace P;
using namespace Q;
进入
using namespace Q;
using namespace P;
我们得到名称查找歧义错误。 GCC 至少在这里是一致的。
我是否正确解释了 c++ 标准?
【问题讨论】:
标签: c++ language-lawyer using-directives name-lookup