4

A::给定没有任何类、模板、枚举或类型定义的翻译单元中的嵌套名称说明符,如果格式正确,则标识符A必须引用命名空间。

例如:

namespace X
{
    int i;
}

int main()
{
    X::i = 42; // Here X:: is a nested-name-specifier
               // and X is a namespace-name
               // i is looked up qualified w.r.t. X
}

在上面的例子A中是X,但是我的问题是关于一般情况的。

名称查找如何在 中进行命名空间A名称A::

名称查找规则在 3.4 中进行了总结,但我不清楚在这种情况下如何(或哪些)适用。

例如,A不合格名称查找的查找?3.4.1适用吗?

换句话说:在哪些命名空间中搜索名为 的命名空间A,以及以什么顺序?你是如何从标准中得出这个结论的?

4

2 回答 2

4

是的,A是根据 3.4.1 进行的常规非限定名称查找,连续搜索包含嵌套名称说明符的范围,除了只找到类和命名空间名称。例如,你可以有这个:

int main()
{
    int X;
    X::i = 42; // OK, int X not found.
}

http://ideone.com/NaEIVd

实际上不建议使用这个漏洞;如果X是类类型的对象,那么X::i可能X.i是完全不同的东西。


为了从标准中得出这个结论,从 3.4.3(合格的查找,这是我们最终要分析的高级构造)开始,它在第 1 段中说,

类或命名空间成员或枚举器的名称可以在应用于表示其类、命名空间或枚举的嵌套名称说明符的 :: 范围解析运算符 (5.1) 之后引用。如果嵌套名称说明符中的 :: 范围解析运算符前面没有 decltype 说明符,则查找 :: 之前的名称仅考虑其特化为类型的名称空间、类型和模板。如果找到的名称没有指定命名空间或类、枚举或依赖类型,则程序是非良构的。

继续阅读第 2 段,它不适用,因为没有声明限定 ID。其余段落同样规定了不适用的例外情况。那么,前面的东西是::什么?参考语法。

nested-name-specifier:
    ::
    type-name ::
    namespace-name ::
    decltype-specifier ::
    nested-name-specifier identifier ::
    nested-name-specifier templateopt simple-template-id ::

只有type-name ::namespace-name ::符合我们的先验标准。这些也与我们迄今为止发现的重叠。在特定的上下文中,type-name或通常是如何解决的?namespace-name不合格的查找。继续 3.4.1。

首先,3.4.1/1 是要记住的一般规则:

在 3.4.1 中列出的所有情况下,按照每个相应类别中列出的顺序搜索范围以查找声明;一旦找到名称的声明,名称查找就会结束。如果没有找到声明,则程序格式错误。

下一个适用的段落是 6:

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

该规则并没有告诉我们在全局命名空间中实际搜索名称,但它确实在列表中提到了函数的封闭命名空间(在本例中为全局命名空间),并且第 1 段说搜索列出的命名空间。所以这足以构建名称查找。

令人惊讶的是,它没有提到优先考虑内部封闭命名空间的递归搜索,但您的示例中实际上并没有这样的东西,所以我会在这里停下来:)。将编译留给编译器要快得多,并且仅在出现问题时手动工作。

于 2013-07-02T23:49:19.123 回答
1

在您给出的示例中,X将被视为不合格的名称查找。因此它确实遵循 3.4.1 中的规则

在这种情况下,搜索的命名空间如下:

  1. main()定义之前的函数的本地命名空间。(根据 7.3.1.4 可能未定义命名空间。)
  2. 全局命名空间。

恐怕我无法指出标准中明确指出命名空间名称与任何其他名称相同的地方。但他们是。名称查找不知道这是一个名称空间名称(它可以是一个类名称或一个结构名称),直到它实际找到具有该名称的名称空间。

于 2013-07-02T23:26:07.593 回答